From d1d713288f868330dd5a8d2fd8b65cd165d4859a Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Wed, 18 Sep 2024 12:02:15 +0600 Subject: [PATCH 01/94] chore(deps): bump go-ebs-file (#7513) Signed-off-by: nikpivkin --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 2ef18dc1cc7a..483b97ee9acc 100644 --- a/go.mod +++ b/go.mod @@ -77,7 +77,7 @@ require ( github.com/liamg/memoryfs v1.6.0 github.com/magefile/mage v1.15.0 github.com/masahiro331/go-disk v0.0.0-20240625071113-56c933208fee - github.com/masahiro331/go-ebs-file v0.0.0-20240112135404-d5fbb1d46323 + github.com/masahiro331/go-ebs-file v0.0.0-20240917043618-e6d2bea5c32e github.com/masahiro331/go-ext4-filesystem v0.0.0-20240620024024-ca14e6327bbd github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08 github.com/masahiro331/go-vmdk-parser v0.0.0-20221225061455-612096e4bbbd @@ -175,7 +175,7 @@ require ( github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/service/ebs v1.21.7 // indirect + github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 // indirect diff --git a/go.sum b/go.sum index daaa23dc6559..6ff7fca55e3b 100644 --- a/go.sum +++ b/go.sum @@ -378,8 +378,8 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 h1:Mqr/V5gvrhA2gvgnF4 github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17/go.mod h1:aLJpZlCmjE+V+KtN1q1uyZkfnUWpQGpbsn89XPKyzfU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/service/ebs v1.21.7 h1:CRzzXjmgx9p362yO39D6hbZULdMI23gaKqSxijJCXHM= -github.com/aws/aws-sdk-go-v2/service/ebs v1.21.7/go.mod h1:wnsHqpi3RgDwklS5SPHUgjcUUpontGPKJ+GJYOdV7pY= +github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1 h1:SeDJWG4pmye+/aO6k+zt9clPTUy1MXqUmkW8rbAddQg= +github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1/go.mod h1:wRzaW0v9GGQS0h//wpsVDw3Hah5gs5UP+NxoyGeZIGM= github.com/aws/aws-sdk-go-v2/service/ec2 v1.177.2 h1:QUUvxEs9q1DsYCaWaRrV8i7n82Adm34jrHb6OPjXPqc= github.com/aws/aws-sdk-go-v2/service/ec2 v1.177.2/go.mod h1:TFSALWR7Xs7+KyMM87ZAYxncKFBvzEt2rpK/BJCH2ps= github.com/aws/aws-sdk-go-v2/service/ecr v1.32.4 h1:nQAU2Yr+afkAvIV39mg7LrNYFNQP7ShwbmiJqx2fUKA= @@ -1023,8 +1023,8 @@ github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/masahiro331/go-disk v0.0.0-20240625071113-56c933208fee h1:cgm8mE25x5XXX2oyvJDlyJ72K+rDu/4ZCYce2worNb8= github.com/masahiro331/go-disk v0.0.0-20240625071113-56c933208fee/go.mod h1:rojbW5tVhH1cuVYFKZS+QX+VGXK45JVsRO+jW92kkKM= -github.com/masahiro331/go-ebs-file v0.0.0-20240112135404-d5fbb1d46323 h1:uQubA711SeYStvStohMLrdvRTTohdPHrEPFzerLcY9I= -github.com/masahiro331/go-ebs-file v0.0.0-20240112135404-d5fbb1d46323/go.mod h1:OdtzwqTtu49Gh5RFkNEU1SbcihIuVTtUipwHflqxckE= +github.com/masahiro331/go-ebs-file v0.0.0-20240917043618-e6d2bea5c32e h1:nCgF1JEYIS8KNuJtIeUrmjjhktIMKWNmASZqwK2ynu0= +github.com/masahiro331/go-ebs-file v0.0.0-20240917043618-e6d2bea5c32e/go.mod h1:XFWPTlAcEL733RUjbr0QBybdt6oK2DH7LZk8id2qtd4= github.com/masahiro331/go-ext4-filesystem v0.0.0-20240620024024-ca14e6327bbd h1:JEIW94K3spsvBI5Xb9PGhKSIza9/jxO1lF30tPCAJlA= github.com/masahiro331/go-ext4-filesystem v0.0.0-20240620024024-ca14e6327bbd/go.mod h1:3XMMY1M486mWGTD13WPItg6FsgflQR72ZMAkd+gsyoQ= github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08 h1:AevUBW4cc99rAF8q8vmddIP8qd/0J5s/UyltGbp66dg= From aeb7039d7ce090e243d29f0bf16c9e4e24252a01 Mon Sep 17 00:00:00 2001 From: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Date: Wed, 18 Sep 2024 12:08:12 +0600 Subject: [PATCH 02/94] fix(sbom): parse type `framework` as `library` when unmarshalling `CycloneDX` files (#7527) --- pkg/sbom/cyclonedx/testdata/happy/third-party-bom.json | 2 +- pkg/sbom/cyclonedx/unmarshal.go | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/sbom/cyclonedx/testdata/happy/third-party-bom.json b/pkg/sbom/cyclonedx/testdata/happy/third-party-bom.json index d8b5068f5cc0..281d3c4fcc30 100644 --- a/pkg/sbom/cyclonedx/testdata/happy/third-party-bom.json +++ b/pkg/sbom/cyclonedx/testdata/happy/third-party-bom.json @@ -46,7 +46,7 @@ }, { "bom-ref": "pkg:composer/pear/pear_exception@v1.0.0", - "type": "library", + "type": "framework", "name": "pear/pear_exception", "version": "v1.0.0", "purl": "pkg:composer/pear/pear_exception@v1.0.0" diff --git a/pkg/sbom/cyclonedx/unmarshal.go b/pkg/sbom/cyclonedx/unmarshal.go index 71a0ee27b640..de410d008794 100644 --- a/pkg/sbom/cyclonedx/unmarshal.go +++ b/pkg/sbom/cyclonedx/unmarshal.go @@ -166,7 +166,10 @@ func (b *BOM) unmarshalType(t cdx.ComponentType) (core.ComponentType, error) { ctype = core.TypeContainerImage case cdx.ComponentTypeApplication: ctype = core.TypeApplication - case cdx.ComponentTypeLibrary: + // There are not many differences between a `library` and a `framework` components, and sometimes it is difficult to choose the right type. + // That is why some users choose `framework` type. + // So we should parse and scan `framework` components as libraries. + case cdx.ComponentTypeLibrary, cdx.ComponentTypeFramework: ctype = core.TypeLibrary case cdx.ComponentTypeOS: ctype = core.TypeOS From dbd2dd60604fbcb5456a864a37d9c1b5a9e6f231 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Wed, 18 Sep 2024 23:41:38 +0600 Subject: [PATCH 03/94] refactor(misconf): pass options to Rego scanner as is (#7529) Signed-off-by: nikpivkin --- pkg/iac/rego/load.go | 18 +- pkg/iac/rego/load_test.go | 49 ++- pkg/iac/rego/options.go | 108 ++++++ pkg/iac/rego/scanner.go | 93 ++---- pkg/iac/rego/scanner_test.go | 311 +++++++++--------- pkg/iac/scanners/azure/arm/scanner.go | 43 +-- pkg/iac/scanners/cloudformation/scanner.go | 44 +-- .../scanners/cloudformation/scanner_test.go | 9 +- .../cloudformation/test/cf_scanning_test.go | 6 +- pkg/iac/scanners/dockerfile/scanner.go | 79 +---- pkg/iac/scanners/dockerfile/scanner_test.go | 12 +- pkg/iac/scanners/helm/scanner.go | 75 +---- pkg/iac/scanners/helm/test/scanner_test.go | 32 +- pkg/iac/scanners/json/scanner.go | 69 +--- pkg/iac/scanners/json/scanner_test.go | 4 +- pkg/iac/scanners/kubernetes/scanner.go | 68 +--- pkg/iac/scanners/kubernetes/scanner_test.go | 40 +-- pkg/iac/scanners/options/scanner.go | 102 +----- pkg/iac/scanners/terraform/fs_test.go | 6 +- pkg/iac/scanners/terraform/ignore_test.go | 9 +- pkg/iac/scanners/terraform/scanner.go | 72 +--- .../terraform/scanner_integration_test.go | 35 +- pkg/iac/scanners/terraform/scanner_test.go | 85 ++--- pkg/iac/scanners/terraform/setup_test.go | 5 +- .../terraformplan/snapshot/scanner_test.go | 25 +- .../scanners/terraformplan/tfjson/scanner.go | 85 +---- .../terraformplan/tfjson/scanner_test.go | 17 +- .../terraformplan/tfjson/test/scanner_test.go | 6 +- pkg/iac/scanners/toml/scanner.go | 65 +--- pkg/iac/scanners/toml/scanner_test.go | 4 +- pkg/iac/scanners/yaml/scanner.go | 64 +--- pkg/iac/scanners/yaml/scanner_test.go | 4 +- pkg/misconf/scanner.go | 21 +- 33 files changed, 570 insertions(+), 1095 deletions(-) create mode 100644 pkg/iac/rego/options.go diff --git a/pkg/iac/rego/load.go b/pkg/iac/rego/load.go index 26a6c9e6f2d1..a1c29d163fae 100644 --- a/pkg/iac/rego/load.go +++ b/pkg/iac/rego/load.go @@ -75,7 +75,7 @@ func (s *Scanner) loadEmbedded() error { return nil } -func (s *Scanner) LoadPolicies(enableEmbeddedLibraries, enableEmbeddedPolicies bool, srcFS fs.FS, paths []string, readers []io.Reader) error { +func (s *Scanner) LoadPolicies(srcFS fs.FS) error { if s.policies == nil { s.policies = make(map[string]*ast.Module) @@ -90,19 +90,19 @@ func (s *Scanner) LoadPolicies(enableEmbeddedLibraries, enableEmbeddedPolicies b return err } - if enableEmbeddedPolicies { + if s.includeEmbeddedPolicies { s.policies = lo.Assign(s.policies, s.embeddedChecks) } - if enableEmbeddedLibraries { + if s.includeEmbeddedLibraries { s.policies = lo.Assign(s.policies, s.embeddedLibs) } var err error - if len(paths) > 0 { - loaded, err := LoadPoliciesFromDirs(srcFS, paths...) + if len(s.policyDirs) > 0 { + loaded, err := LoadPoliciesFromDirs(srcFS, s.policyDirs...) if err != nil { - return fmt.Errorf("failed to load rego checks from %s: %w", paths, err) + return fmt.Errorf("failed to load rego checks from %s: %w", s.policyDirs, err) } for name, policy := range loaded { s.policies[name] = policy @@ -110,8 +110,8 @@ func (s *Scanner) LoadPolicies(enableEmbeddedLibraries, enableEmbeddedPolicies b s.logger.Debug("Checks from disk are loaded", log.Int("count", len(loaded))) } - if len(readers) > 0 { - loaded, err := s.loadPoliciesFromReaders(readers) + if len(s.policyReaders) > 0 { + loaded, err := s.loadPoliciesFromReaders(s.policyReaders) if err != nil { return fmt.Errorf("failed to load rego checks from reader(s): %w", err) } @@ -143,7 +143,7 @@ func (s *Scanner) LoadPolicies(enableEmbeddedLibraries, enableEmbeddedPolicies b } s.store = store - return s.compilePolicies(srcFS, paths) + return s.compilePolicies(srcFS, s.policyDirs) } func (s *Scanner) fallbackChecks(compiler *ast.Compiler) { diff --git a/pkg/iac/rego/load_test.go b/pkg/iac/rego/load_test.go index e0c136562d45..174cbc732525 100644 --- a/pkg/iac/rego/load_test.go +++ b/pkg/iac/rego/load_test.go @@ -4,7 +4,6 @@ import ( "bytes" "embed" "fmt" - "io" "log/slog" "strings" "testing" @@ -16,7 +15,6 @@ import ( checks "github.com/aquasecurity/trivy-checks" "github.com/aquasecurity/trivy/pkg/iac/rego" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" "github.com/aquasecurity/trivy/pkg/iac/types" "github.com/aquasecurity/trivy/pkg/log" ) @@ -33,10 +31,11 @@ func Test_RegoScanning_WithSomeInvalidPolicies(t *testing.T) { slog.SetDefault(log.New(log.NewHandler(&debugBuf, nil))) scanner := rego.NewScanner( types.SourceDockerfile, - options.ScannerWithRegoErrorLimits(0), + rego.WithRegoErrorLimits(0), + rego.WithPolicyDirs("."), ) - err := scanner.LoadPolicies(false, false, testEmbedFS, []string{"."}, nil) + err := scanner.LoadPolicies(testEmbedFS) require.ErrorContains(t, err, `want (one of): ["Cmd" "EndLine" "Flags" "JSON" "Original" "Path" "Stage" "StartLine" "SubCmd" "Value"]`) assert.Contains(t, debugBuf.String(), "Error(s) occurred while loading checks") }) @@ -46,10 +45,11 @@ func Test_RegoScanning_WithSomeInvalidPolicies(t *testing.T) { slog.SetDefault(log.New(log.NewHandler(&debugBuf, nil))) scanner := rego.NewScanner( types.SourceDockerfile, - options.ScannerWithRegoErrorLimits(1), + rego.WithRegoErrorLimits(1), + rego.WithPolicyDirs("."), ) - err := scanner.LoadPolicies(false, false, testEmbedFS, []string{"."}, nil) + err := scanner.LoadPolicies(testEmbedFS) require.NoError(t, err) assert.Contains(t, debugBuf.String(), "Error occurred while parsing\tfile_path=\"testdata/policies/invalid.rego\" err=\"testdata/policies/invalid.rego:7") @@ -64,9 +64,13 @@ package mypackage deny { input.evil == "foo bar" }` - scanner := rego.NewScanner(types.SourceJSON) + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("."), + rego.WithPolicyReader(strings.NewReader(check)), + ) - err := scanner.LoadPolicies(false, false, fstest.MapFS{}, []string{"."}, []io.Reader{strings.NewReader(check)}) + err := scanner.LoadPolicies(fstest.MapFS{}) assert.ErrorContains(t, err, "could not find schema \"fooschema\"") }) @@ -79,7 +83,11 @@ package mypackage deny { input.evil == "foo bar" }` - scanner := rego.NewScanner(types.SourceJSON) + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("."), + rego.WithPolicyReader(strings.NewReader(check)), + ) fsys := fstest.MapFS{ "schemas/fooschema.json": &fstest.MapFile{ @@ -87,7 +95,7 @@ deny { }, } - err := scanner.LoadPolicies(false, false, fsys, []string{"."}, []io.Reader{strings.NewReader(check)}) + err := scanner.LoadPolicies(fsys) assert.ErrorContains(t, err, "could not parse schema \"fooschema\"") }) @@ -97,8 +105,12 @@ deny { deny { input.evil == "foo bar" }` - scanner := rego.NewScanner(types.SourceJSON) - err := scanner.LoadPolicies(false, false, fstest.MapFS{}, []string{"."}, []io.Reader{strings.NewReader(check)}) + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("."), + rego.WithPolicyReader(strings.NewReader(check)), + ) + err := scanner.LoadPolicies(fstest.MapFS{}) require.NoError(t, err) }) @@ -184,8 +196,9 @@ deny { t.Run(tt.name, func(t *testing.T) { scanner := rego.NewScanner( types.SourceDockerfile, - options.ScannerWithRegoErrorLimits(0), - options.ScannerWithEmbeddedPolicies(false), + rego.WithRegoErrorLimits(0), + rego.WithEmbeddedPolicies(false), + rego.WithPolicyDirs("."), ) tt.files["schemas/fooschema.json"] = &fstest.MapFile{ @@ -200,9 +213,8 @@ deny { }`), } - fsys := fstest.MapFS(tt.files) checks.EmbeddedPolicyFileSystem = embeddedChecksFS - err := scanner.LoadPolicies(false, false, fsys, []string{"."}, nil) + err := scanner.LoadPolicies(fstest.MapFS(tt.files)) if tt.expectedErr != "" { assert.ErrorContains(t, err, tt.expectedErr) @@ -244,8 +256,9 @@ deny { scanner := rego.NewScanner( types.SourceDockerfile, - options.ScannerWithEmbeddedPolicies(false), + rego.WithEmbeddedPolicies(false), + rego.WithPolicyDirs("."), ) - err := scanner.LoadPolicies(false, false, fsys, []string{"."}, nil) + err := scanner.LoadPolicies(fsys) require.Error(t, err) } diff --git a/pkg/iac/rego/options.go b/pkg/iac/rego/options.go new file mode 100644 index 000000000000..d4b622a68c16 --- /dev/null +++ b/pkg/iac/rego/options.go @@ -0,0 +1,108 @@ +package rego + +import ( + "io" + "io/fs" + + "github.com/aquasecurity/trivy/pkg/iac/scanners/options" +) + +func WithPolicyReader(readers ...io.Reader) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.policyReaders = readers + } + } +} + +func WithEmbeddedPolicies(include bool) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.includeEmbeddedPolicies = include + } + } +} + +func WithEmbeddedLibraries(include bool) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.includeEmbeddedLibraries = include + } + } +} + +// WithTrace specifies an io.Writer for trace logs (mainly rego tracing) - if not set, they are discarded +func WithTrace(w io.Writer) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.traceWriter = w + } + } +} + +func WithPerResultTracing(enabled bool) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.tracePerResult = enabled + } + } +} + +func WithPolicyDirs(paths ...string) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.policyDirs = paths + } + } +} + +func WithDataDirs(paths ...string) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.dataDirs = paths + } + } +} + +// WithPolicyNamespaces - namespaces which indicate rego policies containing enforced rules +func WithPolicyNamespaces(namespaces ...string) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + for _, namespace := range namespaces { + ss.ruleNamespaces[namespace] = struct{}{} + } + } + } +} + +func WithPolicyFilesystem(fsys fs.FS) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.policyFS = fsys + } + } +} + +func WithDataFilesystem(fsys fs.FS) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.dataFS = fsys + } + } +} + +func WithRegoErrorLimits(limit int) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.regoErrorLimit = limit + } + } +} + +func WithCustomSchemas(schemas map[string][]byte) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.customSchemas = schemas + } + } +} diff --git a/pkg/iac/rego/scanner.go b/pkg/iac/rego/scanner.go index f6108ffefd66..a8e1caf525b3 100644 --- a/pkg/iac/rego/scanner.go +++ b/pkg/iac/rego/scanner.go @@ -44,24 +44,27 @@ func makeSupportedProviders() map[string]struct{} { var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - ruleNamespaces map[string]struct{} - policies map[string]*ast.Module - store storage.Store - dataDirs []string - runtimeValues *ast.Term - compiler *ast.Compiler - regoErrorLimit int - logger *log.Logger - traceWriter io.Writer - tracePerResult bool - retriever *MetadataRetriever - policyFS fs.FS - dataFS fs.FS - frameworks []framework.Framework - spec string - inputSchema any // unmarshalled into this from a json schema document - sourceType types.Source - includeDeprecatedChecks bool + ruleNamespaces map[string]struct{} + policies map[string]*ast.Module + store storage.Store + runtimeValues *ast.Term + compiler *ast.Compiler + regoErrorLimit int + logger *log.Logger + traceWriter io.Writer + tracePerResult bool + retriever *MetadataRetriever + policyFS fs.FS + policyDirs []string + policyReaders []io.Reader + dataFS fs.FS + dataDirs []string + frameworks []framework.Framework + inputSchema any // unmarshalled into this from a json schema document + sourceType types.Source + includeDeprecatedChecks bool + includeEmbeddedPolicies bool + includeEmbeddedLibraries bool embeddedLibs map[string]*ast.Module embeddedChecks map[string]*ast.Module @@ -72,24 +75,12 @@ func (s *Scanner) SetIncludeDeprecatedChecks(b bool) { s.includeDeprecatedChecks = b } -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - // handled externally -} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - func (s *Scanner) SetRegoOnly(bool) {} func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { s.frameworks = frameworks } -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - // handled externally -} - func (s *Scanner) trace(heading string, input any) { if s.traceWriter == nil { return @@ -101,48 +92,6 @@ func (s *Scanner) trace(heading string, input any) { _, _ = fmt.Fprintf(s.traceWriter, "REGO %[1]s:\n%s\nEND REGO %[1]s\n\n", heading, string(data)) } -func (s *Scanner) SetPolicyFilesystem(fsys fs.FS) { - s.policyFS = fsys -} - -func (s *Scanner) SetDataFilesystem(fsys fs.FS) { - s.dataFS = fsys -} - -func (s *Scanner) SetPolicyReaders(_ []io.Reader) { - // NOTE: Policy readers option not applicable for rego, policies are loaded on-demand by other scanners. -} - -func (s *Scanner) SetTraceWriter(writer io.Writer) { - s.traceWriter = writer -} - -func (s *Scanner) SetPerResultTracingEnabled(b bool) { - s.tracePerResult = b -} - -func (s *Scanner) SetPolicyDirs(_ ...string) { - // NOTE: Policy dirs option not applicable for rego, policies are loaded on-demand by other scanners. -} - -func (s *Scanner) SetDataDirs(dirs ...string) { - s.dataDirs = dirs -} - -func (s *Scanner) SetPolicyNamespaces(namespaces ...string) { - for _, namespace := range namespaces { - s.ruleNamespaces[namespace] = struct{}{} - } -} - -func (s *Scanner) SetRegoErrorLimit(limit int) { - s.regoErrorLimit = limit -} - -func (s *Scanner) SetCustomSchemas(v map[string][]byte) { - s.customSchemas = v -} - type DynamicMetadata struct { Warning bool Filepath string diff --git a/pkg/iac/rego/scanner_test.go b/pkg/iac/rego/scanner_test.go index c453cc984b1c..73ef55223f14 100644 --- a/pkg/iac/rego/scanner_test.go +++ b/pkg/iac/rego/scanner_test.go @@ -1,9 +1,8 @@ -package rego +package rego_test import ( "bytes" "context" - "io" "io/fs" "os" "path/filepath" @@ -15,7 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/severity" "github.com/aquasecurity/trivy/pkg/iac/types" ) @@ -44,13 +43,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -79,13 +78,13 @@ deny { srcFS := os.DirFS(tmp) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"/policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -114,13 +113,13 @@ warn { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -146,13 +145,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": false, @@ -189,13 +188,13 @@ exception[ns] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -237,13 +236,13 @@ exception[ns] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -274,13 +273,13 @@ exception[rules] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -310,13 +309,13 @@ exception[rules] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -344,13 +343,13 @@ deny_evil { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -375,13 +374,13 @@ deny[msg] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -413,13 +412,13 @@ deny[res] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -455,13 +454,13 @@ deny[res] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -509,13 +508,13 @@ deny[res] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -558,13 +557,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -592,13 +591,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -623,13 +622,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -658,13 +657,14 @@ deny { traceBuffer := bytes.NewBuffer([]byte{}) - scanner := NewScanner(types.SourceJSON, options.ScannerWithTrace(traceBuffer)) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithTrace(traceBuffer), + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -692,13 +692,14 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON, options.ScannerWithPerResultTracing(true)) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPerResultTracing(true), + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -730,13 +731,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "text": "dynamic", @@ -763,13 +764,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "text": "test", @@ -810,13 +811,14 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPerResultTracing(true), + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "text": "test", @@ -848,13 +850,11 @@ deny { `, }) - scanner := NewScanner(types.SourceDockerfile) - scanner.SetRegoErrorLimit(0) // override to not allow any errors - assert.ErrorContains( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), - "undefined ref: input.evil", + scanner := rego.NewScanner( + types.SourceDockerfile, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) } func Test_RegoScanning_WithValidInputSchema(t *testing.T) { @@ -871,11 +871,11 @@ deny { `, }) - scanner := NewScanner(types.SourceDockerfile) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceDockerfile, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) } func Test_RegoScanning_WithFilepathToSchema(t *testing.T) { @@ -890,11 +890,16 @@ deny { } `, }) - scanner := NewScanner(types.SourceJSON) - scanner.SetRegoErrorLimit(0) // override to not allow any errors + + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithRegoErrorLimits(0), + rego.WithPolicyDirs("policies"), + ) + assert.ErrorContains( t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner.LoadPolicies(srcFS), "undefined ref: input.evil", ) } @@ -922,16 +927,16 @@ deny { "data/junk.txt": "this file should be ignored", }) - scanner := NewScanner(types.SourceJSON) - scanner.SetDataFilesystem(dataFS) - scanner.SetDataDirs(".") - - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithDataFilesystem(dataFS), + rego.WithDataDirs("."), + rego.WithPolicyDirs("policies"), ) - results, err := scanner.ScanInput(context.TODO(), Input{}) + require.NoError(t, scanner.LoadPolicies(srcFS)) + + results, err := scanner.ScanInput(context.TODO(), rego.Input{}) require.NoError(t, err) assert.Len(t, results.GetFailed(), 1) @@ -962,16 +967,16 @@ deny { "data/junk.txt": "this file should be ignored", }) - scanner := NewScanner(types.SourceJSON) - scanner.SetDataFilesystem(dataFS) - scanner.SetDataDirs("X://") - - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithDataFilesystem(dataFS), + rego.WithDataDirs("X://"), + rego.WithPolicyDirs("policies"), ) - results, err := scanner.ScanInput(context.TODO(), Input{}) + require.NoError(t, scanner.LoadPolicies(srcFS)) + + results, err := scanner.ScanInput(context.TODO(), rego.Input{}) require.NoError(t, err) assert.Len(t, results.GetFailed(), 1) @@ -998,14 +1003,12 @@ deny { }, } - scanner := NewScanner( + scanner := rego.NewScanner( types.SourceYAML, + rego.WithPolicyDirs("checks"), ) - require.NoError( - t, - scanner.LoadPolicies(false, false, fsys, []string{"checks"}, nil), - ) - _, err := scanner.ScanInput(context.TODO(), Input{}) + require.NoError(t, scanner.LoadPolicies(fsys)) + _, err := scanner.ScanInput(context.TODO(), rego.Input{}) require.NoError(t, err) } @@ -1066,13 +1069,10 @@ deny { "policies/test.rego": tc.policy, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), - ) + scanner := rego.NewScanner(types.SourceJSON, rego.WithPolicyDirs("policies")) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "text": "test", @@ -1133,17 +1133,18 @@ deny { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - scanner := NewScanner( + scanner := rego.NewScanner( types.SourceYAML, - options.ScannerWithCustomSchemas(map[string][]byte{ + rego.WithCustomSchemas(map[string][]byte{ "test": []byte(schema), }), - options.ScannerWithPolicyNamespaces("user"), + rego.WithPolicyNamespaces("user"), + rego.WithPolicyReader(strings.NewReader(tc.check)), ) - err := scanner.LoadPolicies(false, false, nil, nil, []io.Reader{strings.NewReader(tc.check)}) - require.NoError(t, err) - results, err := scanner.ScanInput(context.TODO(), Input{ + require.NoError(t, scanner.LoadPolicies(nil)) + + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "test.yaml", Contents: map[string]any{"service": "test"}, }) diff --git a/pkg/iac/scanners/azure/arm/scanner.go b/pkg/iac/scanners/azure/arm/scanner.go index e4b3258f823f..410ccd6d18df 100644 --- a/pkg/iac/scanners/azure/arm/scanner.go +++ b/pkg/iac/scanners/azure/arm/scanner.go @@ -3,7 +3,6 @@ package arm import ( "context" "fmt" - "io" "io/fs" "sync" @@ -30,12 +29,7 @@ type Scanner struct { logger *log.Logger frameworks []framework.Framework regoOnly bool - loadEmbeddedPolicies bool - loadEmbeddedLibraries bool - policyDirs []string - policyReaders []io.Reader regoScanner *rego.Scanner - spec string includeDeprecatedChecks bool } @@ -43,12 +37,6 @@ func (s *Scanner) SetIncludeDeprecatedChecks(b bool) { s.includeDeprecatedChecks = b } -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - func (s *Scanner) SetRegoOnly(regoOnly bool) { s.regoOnly = regoOnly } @@ -68,39 +56,10 @@ func (s *Scanner) Name() string { return "Azure ARM" } -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} - func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { s.frameworks = frameworks } -func (s *Scanner) SetTraceWriter(io.Writer) {} -func (s *Scanner) SetPerResultTracingEnabled(bool) {} -func (s *Scanner) SetDataDirs(...string) {} -func (s *Scanner) SetPolicyNamespaces(...string) {} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - func (s *Scanner) initRegoScanner(srcFS fs.FS) error { s.mu.Lock() defer s.mu.Unlock() @@ -108,7 +67,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) error { return nil } regoScanner := rego.NewScanner(types.SourceCloud, s.scannerOptions...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/cloudformation/scanner.go b/pkg/iac/scanners/cloudformation/scanner.go index dc4deab0aff5..4497a807506c 100644 --- a/pkg/iac/scanners/cloudformation/scanner.go +++ b/pkg/iac/scanners/cloudformation/scanner.go @@ -3,7 +3,6 @@ package cloudformation import ( "context" "fmt" - "io" "io/fs" "sort" "sync" @@ -50,17 +49,12 @@ var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { mu sync.Mutex logger *log.Logger - policyDirs []string - policyReaders []io.Reader parser *parser.Parser regoScanner *rego.Scanner regoOnly bool - loadEmbeddedPolicies bool - loadEmbeddedLibraries bool options []options.ScannerOption parserOptions []parser.Option frameworks []framework.Framework - spec string includeDeprecatedChecks bool } @@ -68,8 +62,6 @@ func (s *Scanner) SetIncludeDeprecatedChecks(b bool) { s.includeDeprecatedChecks = b } -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - func (s *Scanner) addParserOption(opt parser.Option) { s.parserOptions = append(s.parserOptions, opt) } @@ -78,18 +70,6 @@ func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { s.frameworks = frameworks } -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} - func (s *Scanner) SetRegoOnly(regoOnly bool) { s.regoOnly = regoOnly } @@ -98,28 +78,6 @@ func (s *Scanner) Name() string { return "CloudFormation" } -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - -func (s *Scanner) SetTraceWriter(_ io.Writer) {} -func (s *Scanner) SetPerResultTracingEnabled(_ bool) {} -func (s *Scanner) SetDataDirs(_ ...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) {} - // New creates a new Scanner func New(opts ...options.ScannerOption) *Scanner { s := &Scanner{ @@ -140,7 +98,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { return s.regoScanner, nil } regoScanner := rego.NewScanner(types.SourceCloud, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/cloudformation/scanner_test.go b/pkg/iac/scanners/cloudformation/scanner_test.go index 21d185c5ec06..67ee92cf69c3 100644 --- a/pkg/iac/scanners/cloudformation/scanner_test.go +++ b/pkg/iac/scanners/cloudformation/scanner_test.go @@ -10,6 +10,7 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) @@ -57,7 +58,7 @@ deny[res] { `, }) - scanner := New(options.ScannerWithPolicyDirs("rules"), options.ScannerWithRegoOnly(true)) + scanner := New(rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true)) results, err := scanner.ScanFS(context.TODO(), fs, "code") require.NoError(t, err) @@ -215,9 +216,9 @@ Resources: scanner := New( options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithPolicyReader(strings.NewReader(bucketNameCheck)), - options.ScannerWithPolicyNamespaces("user"), + rego.WithEmbeddedPolicies(false), + rego.WithPolicyReader(strings.NewReader(bucketNameCheck)), + rego.WithPolicyNamespaces("user"), ) results, err := scanner.ScanFS(context.TODO(), fsys, "code") diff --git a/pkg/iac/scanners/cloudformation/test/cf_scanning_test.go b/pkg/iac/scanners/cloudformation/test/cf_scanning_test.go index 396963447ca9..46eed857a75f 100644 --- a/pkg/iac/scanners/cloudformation/test/cf_scanning_test.go +++ b/pkg/iac/scanners/cloudformation/test/cf_scanning_test.go @@ -8,12 +8,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) func Test_basic_cloudformation_scanning(t *testing.T) { - cfScanner := cloudformation.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + cfScanner := cloudformation.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) results, err := cfScanner.ScanFS(context.TODO(), os.DirFS("./examples/bucket"), ".") require.NoError(t, err) @@ -22,7 +22,7 @@ func Test_basic_cloudformation_scanning(t *testing.T) { } func Test_cloudformation_scanning_has_expected_errors(t *testing.T) { - cfScanner := cloudformation.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + cfScanner := cloudformation.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) results, err := cfScanner.ScanFS(context.TODO(), os.DirFS("./examples/bucket"), ".") require.NoError(t, err) diff --git a/pkg/iac/scanners/dockerfile/scanner.go b/pkg/iac/scanners/dockerfile/scanner.go index e0d6ebd9ebde..1694f28d814a 100644 --- a/pkg/iac/scanners/dockerfile/scanner.go +++ b/pkg/iac/scanners/dockerfile/scanner.go @@ -2,7 +2,6 @@ package dockerfile import ( "context" - "io" "io/fs" "sync" @@ -20,81 +19,21 @@ var _ scanners.FSScanner = (*Scanner)(nil) var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - logger *log.Logger - policyDirs []string - policyReaders []io.Reader - parser *parser.Parser - regoScanner *rego.Scanner - options []options.ScannerOption - frameworks []framework.Framework - spec string - loadEmbeddedLibraries bool - loadEmbeddedPolicies bool + mu sync.Mutex + logger *log.Logger + parser *parser.Parser + regoScanner *rego.Scanner + options []options.ScannerOption } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetRegoOnly(bool) { -} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} +func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} +func (s *Scanner) SetRegoOnly(bool) {} +func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} func (s *Scanner) Name() string { return "Dockerfile" } -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPerResultTracingEnabled(_ bool) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(_ ...string) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPolicyNamespaces(_ ...string) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetRegoErrorLimit(_ int) { - // handled by rego when option is passed on -} - func NewScanner(opts ...options.ScannerOption) *Scanner { s := &Scanner{ options: opts, @@ -154,7 +93,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { } regoScanner := rego.NewScanner(types.SourceDockerfile, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/dockerfile/scanner_test.go b/pkg/iac/scanners/dockerfile/scanner_test.go index 4cbd86667a17..2872df1e4ef6 100644 --- a/pkg/iac/scanners/dockerfile/scanner_test.go +++ b/pkg/iac/scanners/dockerfile/scanner_test.go @@ -10,9 +10,9 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/rego/schemas" "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) const DS006PolicyWithDockerfileSchema = `# METADATA @@ -219,7 +219,7 @@ USER root "/rules/rule.rego": DS006LegacyWithOldStyleMetadata, }) - scanner := NewScanner(options.ScannerWithPolicyDirs("rules")) + scanner := NewScanner(rego.WithPolicyDirs("rules")) results, err := scanner.ScanFS(context.TODO(), fs, "code") require.NoError(t, err) @@ -564,10 +564,10 @@ COPY --from=dep /binary /` var traceBuf bytes.Buffer scanner := NewScanner( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithTrace(&traceBuf), - options.ScannerWithRegoErrorLimits(0), + rego.WithPolicyDirs("rules"), + rego.WithEmbeddedLibraries(true), + rego.WithTrace(&traceBuf), + rego.WithRegoErrorLimits(0), ) results, err := scanner.ScanFS(context.TODO(), fsys, "code") diff --git a/pkg/iac/scanners/helm/scanner.go b/pkg/iac/scanners/helm/scanner.go index 305a116b56b7..bfa63a5d2c00 100644 --- a/pkg/iac/scanners/helm/scanner.go +++ b/pkg/iac/scanners/helm/scanner.go @@ -27,34 +27,16 @@ var _ scanners.FSScanner = (*Scanner)(nil) var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - policyDirs []string - dataDirs []string - logger *log.Logger - options []options.ScannerOption - parserOptions []parser.Option - policyReaders []io.Reader - loadEmbeddedLibraries bool - loadEmbeddedPolicies bool - policyFS fs.FS - frameworks []framework.Framework - spec string - regoScanner *rego.Scanner - mu sync.Mutex + mu sync.Mutex + logger *log.Logger + options []options.ScannerOption + parserOptions []parser.Option + regoScanner *rego.Scanner } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetRegoOnly(bool) { -} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} +func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} +func (s *Scanner) SetRegoOnly(bool) {} +func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} // New creates a new Scanner func New(opts ...options.ScannerOption) *Scanner { @@ -73,49 +55,10 @@ func (s *Scanner) addParserOptions(opts ...parser.Option) { s.parserOptions = append(s.parserOptions, opts...) } -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} - func (s *Scanner) Name() string { return "Helm" } -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPerResultTracingEnabled(_ bool) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(dirs ...string) { - s.dataDirs = dirs -} - -func (s *Scanner) SetPolicyNamespaces(namespaces ...string) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPolicyFilesystem(policyFS fs.FS) { - s.policyFS = policyFS -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) {} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - func (s *Scanner) ScanFS(ctx context.Context, target fs.FS, path string) (scan.Results, error) { if err := s.initRegoScanner(target); err != nil { @@ -228,7 +171,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) error { return nil } regoScanner := rego.NewScanner(types.SourceKubernetes, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/helm/test/scanner_test.go b/pkg/iac/scanners/helm/test/scanner_test.go index 45a426762439..ef751ac2a7b8 100644 --- a/pkg/iac/scanners/helm/test/scanner_test.go +++ b/pkg/iac/scanners/helm/test/scanner_test.go @@ -13,8 +13,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scanners/helm" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) func Test_helm_scanner_with_archive(t *testing.T) { @@ -40,7 +40,7 @@ func Test_helm_scanner_with_archive(t *testing.T) { for _, test := range tests { t.Logf("Running test: %s", test.testName) - helmScanner := helm.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + helmScanner := helm.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) testTemp := t.TempDir() testFileName := filepath.Join(testTemp, test.archiveName) @@ -96,7 +96,7 @@ func Test_helm_scanner_with_missing_name_can_recover(t *testing.T) { for _, test := range tests { t.Logf("Running test: %s", test.testName) - helmScanner := helm.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + helmScanner := helm.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) testTemp := t.TempDir() testFileName := filepath.Join(testTemp, test.archiveName) @@ -128,7 +128,7 @@ func Test_helm_scanner_with_dir(t *testing.T) { t.Logf("Running test: %s", test.testName) - helmScanner := helm.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + helmScanner := helm.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) testFs := os.DirFS(filepath.Join("testdata", test.chartName)) results, err := helmScanner.ScanFS(context.TODO(), testFs, ".") @@ -209,9 +209,9 @@ deny[res] { t.Run(test.testName, func(t *testing.T) { t.Logf("Running test: %s", test.testName) - helmScanner := helm.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyNamespaces("user")) + helmScanner := helm.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true), + rego.WithPolicyDirs("rules"), + rego.WithPolicyNamespaces("user")) testTemp := t.TempDir() testFileName := filepath.Join(testTemp, test.archiveName) @@ -274,7 +274,7 @@ func copyArchive(src, dst string) error { } func Test_helm_chart_with_templated_name(t *testing.T) { - helmScanner := helm.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + helmScanner := helm.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) testFs := os.DirFS(filepath.Join("testdata", "templated-name")) _, err := helmScanner.ScanFS(context.TODO(), testFs, ".") require.NoError(t, err) @@ -302,10 +302,10 @@ deny[res] { } ` helmScanner := helm.New( - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithPolicyNamespaces("user"), - options.ScannerWithPolicyReader(strings.NewReader(policy)), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), + rego.WithPolicyNamespaces("user"), + rego.WithPolicyReader(strings.NewReader(policy)), ) results, err := helmScanner.ScanFS(context.TODO(), os.DirFS("testdata/simmilar-templates"), ".") @@ -348,10 +348,10 @@ deny[res] { ` scanner := helm.New( - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithPolicyNamespaces("user"), - options.ScannerWithPolicyReader(strings.NewReader(check)), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(true), + rego.WithPolicyNamespaces("user"), + rego.WithPolicyReader(strings.NewReader(check)), ) results, err := scanner.ScanFS(context.TODO(), os.DirFS("testdata/with-subchart"), ".") diff --git a/pkg/iac/scanners/json/scanner.go b/pkg/iac/scanners/json/scanner.go index 8991120be26f..f46f9cc56bc9 100644 --- a/pkg/iac/scanners/json/scanner.go +++ b/pkg/iac/scanners/json/scanner.go @@ -2,7 +2,6 @@ package json import ( "context" - "io" "io/fs" "sync" @@ -20,66 +19,16 @@ var _ scanners.FSScanner = (*Scanner)(nil) var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - logger *log.Logger - policyDirs []string - policyReaders []io.Reader - parser *parser.Parser - regoScanner *rego.Scanner - options []options.ScannerOption - frameworks []framework.Framework - spec string - loadEmbeddedPolicies bool - loadEmbeddedLibraries bool + mu sync.Mutex + logger *log.Logger + parser *parser.Parser + regoScanner *rego.Scanner + options []options.ScannerOption } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetRegoOnly(bool) { -} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} - -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) { -} - -func (s *Scanner) SetPerResultTracingEnabled(_ bool) { -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(_ ...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) {} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} +func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} +func (s *Scanner) SetRegoOnly(bool) {} +func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} func NewScanner(opts ...options.ScannerOption) *Scanner { s := &Scanner{ @@ -143,7 +92,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { return s.regoScanner, nil } regoScanner := rego.NewScanner(types.SourceJSON, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/json/scanner_test.go b/pkg/iac/scanners/json/scanner_test.go index e126768e55d8..6656f70b2e25 100644 --- a/pkg/iac/scanners/json/scanner_test.go +++ b/pkg/iac/scanners/json/scanner_test.go @@ -9,8 +9,8 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) func Test_BasicScan(t *testing.T) { @@ -48,7 +48,7 @@ deny[res] { `, }) - scanner := NewScanner(options.ScannerWithPolicyDirs("rules")) + scanner := NewScanner(rego.WithPolicyDirs("rules")) results, err := scanner.ScanFS(context.TODO(), fs, "code") require.NoError(t, err) diff --git a/pkg/iac/scanners/kubernetes/scanner.go b/pkg/iac/scanners/kubernetes/scanner.go index e9e9eacd73e8..dfd248cc8b1d 100644 --- a/pkg/iac/scanners/kubernetes/scanner.go +++ b/pkg/iac/scanners/kubernetes/scanner.go @@ -24,66 +24,16 @@ var _ scanners.FSScanner = (*Scanner)(nil) var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - logger *log.Logger - options []options.ScannerOption - policyDirs []string - policyReaders []io.Reader - regoScanner *rego.Scanner - parser *parser.Parser - loadEmbeddedPolicies bool - frameworks []framework.Framework - spec string - loadEmbeddedLibraries bool + mu sync.Mutex + logger *log.Logger + options []options.ScannerOption + regoScanner *rego.Scanner + parser *parser.Parser } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetRegoOnly(bool) {} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} - -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) { -} - -func (s *Scanner) SetPerResultTracingEnabled(_ bool) { -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) { -} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} +func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} +func (s *Scanner) SetRegoOnly(bool) {} +func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} func NewScanner(opts ...options.ScannerOption) *Scanner { s := &Scanner{ @@ -108,7 +58,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { return s.regoScanner, nil } regoScanner := rego.NewScanner(types.SourceKubernetes, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/kubernetes/scanner_test.go b/pkg/iac/scanners/kubernetes/scanner_test.go index c981634a0ee6..ef1ac38560f4 100644 --- a/pkg/iac/scanners/kubernetes/scanner_test.go +++ b/pkg/iac/scanners/kubernetes/scanner_test.go @@ -11,8 +11,8 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) func Test_BasicScan_YAML(t *testing.T) { @@ -94,8 +94,8 @@ deny[res] { }) scanner := NewScanner( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithEmbeddedLibraries(true), + rego.WithPolicyDirs("rules"), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "code") @@ -256,8 +256,8 @@ deny[res] { }) scanner := NewScanner( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithEmbeddedLibraries(true), + rego.WithPolicyDirs("rules"), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "code") @@ -330,7 +330,7 @@ deny[res] { func Test_FileScan(t *testing.T) { - results, err := NewScanner(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true), options.ScannerWithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(` + results, err := NewScanner(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true), rego.WithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(` apiVersion: v1 kind: Pod metadata: @@ -348,7 +348,7 @@ spec: func Test_FileScan_WithSeparator(t *testing.T) { - results, err := NewScanner(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(` + results, err := NewScanner(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(` --- --- apiVersion: v1 @@ -391,9 +391,9 @@ spec: ` results, err := NewScanner( - options.ScannerWithEmbeddedPolicies(true), - options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(file)) + rego.WithEmbeddedPolicies(true), + rego.WithEmbeddedLibraries(true), + rego.WithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(file)) require.NoError(t, err) assert.Greater(t, len(results.GetFailed()), 1) @@ -411,7 +411,7 @@ spec: func Test_FileScanWithPolicyReader(t *testing.T) { - results, err := NewScanner(options.ScannerWithPolicyReader(strings.NewReader(`package defsec + results, err := NewScanner(rego.WithPolicyReader(strings.NewReader(`package defsec deny[msg] { msg = "fail" @@ -434,7 +434,7 @@ spec: func Test_FileScanJSON(t *testing.T) { - results, err := NewScanner(options.ScannerWithPolicyReader(strings.NewReader(`package defsec + results, err := NewScanner(rego.WithPolicyReader(strings.NewReader(`package defsec deny[msg] { input.kind == "Pod" @@ -490,8 +490,8 @@ deny[msg] { func Test_FileScanWithMetadata(t *testing.T) { results, err := NewScanner( - options.ScannerWithTrace(os.Stdout), - options.ScannerWithPolicyReader(strings.NewReader(`package defsec + rego.WithTrace(os.Stdout), + rego.WithPolicyReader(strings.NewReader(`package defsec deny[msg] { input.kind == "Pod" @@ -529,8 +529,8 @@ spec: func Test_FileScanExampleWithResultFunction(t *testing.T) { results, err := NewScanner( - options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithPolicyReader(strings.NewReader(`package defsec + rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true), + rego.WithPolicyReader(strings.NewReader(`package defsec import data.lib.kubernetes @@ -707,10 +707,10 @@ spec: }) scanner := NewScanner( - // options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithPolicyDirs("policies/"), - options.ScannerWithPolicyFilesystem(srcFS), + // rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true), + rego.WithEmbeddedLibraries(true), + rego.WithPolicyDirs("policies/"), + rego.WithPolicyFilesystem(srcFS), ) results, err := scanner.ScanFS(context.TODO(), srcFS, "test/KSV001") require.NoError(t, err) diff --git a/pkg/iac/scanners/options/scanner.go b/pkg/iac/scanners/options/scanner.go index 4f07c4d14b0a..a9561d95130a 100644 --- a/pkg/iac/scanners/options/scanner.go +++ b/pkg/iac/scanners/options/scanner.go @@ -1,61 +1,13 @@ package options import ( - "io" - "io/fs" - "github.com/aquasecurity/trivy/pkg/iac/framework" ) type ConfigurableScanner interface { - SetTraceWriter(io.Writer) - SetPerResultTracingEnabled(bool) - SetPolicyDirs(...string) - SetDataDirs(...string) - SetPolicyNamespaces(...string) - SetPolicyReaders([]io.Reader) - SetPolicyFilesystem(fs.FS) - SetDataFilesystem(fs.FS) - SetUseEmbeddedPolicies(bool) SetFrameworks(frameworks []framework.Framework) - SetSpec(spec string) SetRegoOnly(regoOnly bool) - SetRegoErrorLimit(limit int) - SetUseEmbeddedLibraries(bool) SetIncludeDeprecatedChecks(bool) - SetCustomSchemas(map[string][]byte) -} - -type ScannerOption func(s ConfigurableScanner) - -func ScannerWithFrameworks(frameworks ...framework.Framework) ScannerOption { - return func(s ConfigurableScanner) { - s.SetFrameworks(frameworks) - } -} - -func ScannerWithSpec(spec string) ScannerOption { - return func(s ConfigurableScanner) { - s.SetSpec(spec) - } -} - -func ScannerWithPolicyReader(readers ...io.Reader) ScannerOption { - return func(s ConfigurableScanner) { - s.SetPolicyReaders(readers) - } -} - -func ScannerWithEmbeddedPolicies(embedded bool) ScannerOption { - return func(s ConfigurableScanner) { - s.SetUseEmbeddedPolicies(embedded) - } -} - -func ScannerWithEmbeddedLibraries(enabled bool) ScannerOption { - return func(s ConfigurableScanner) { - s.SetUseEmbeddedLibraries(enabled) - } } func ScannerWithIncludeDeprecatedChecks(enabled bool) ScannerOption { @@ -64,47 +16,11 @@ func ScannerWithIncludeDeprecatedChecks(enabled bool) ScannerOption { } } -// ScannerWithTrace specifies an io.Writer for trace logs (mainly rego tracing) - if not set, they are discarded -func ScannerWithTrace(w io.Writer) ScannerOption { - return func(s ConfigurableScanner) { - s.SetTraceWriter(w) - } -} - -func ScannerWithPerResultTracing(enabled bool) ScannerOption { - return func(s ConfigurableScanner) { - s.SetPerResultTracingEnabled(enabled) - } -} - -func ScannerWithPolicyDirs(paths ...string) ScannerOption { - return func(s ConfigurableScanner) { - s.SetPolicyDirs(paths...) - } -} - -func ScannerWithDataDirs(paths ...string) ScannerOption { - return func(s ConfigurableScanner) { - s.SetDataDirs(paths...) - } -} - -// ScannerWithPolicyNamespaces - namespaces which indicate rego policies containing enforced rules -func ScannerWithPolicyNamespaces(namespaces ...string) ScannerOption { - return func(s ConfigurableScanner) { - s.SetPolicyNamespaces(namespaces...) - } -} - -func ScannerWithPolicyFilesystem(f fs.FS) ScannerOption { - return func(s ConfigurableScanner) { - s.SetPolicyFilesystem(f) - } -} +type ScannerOption func(s ConfigurableScanner) -func ScannerWithDataFilesystem(f fs.FS) ScannerOption { +func ScannerWithFrameworks(frameworks ...framework.Framework) ScannerOption { return func(s ConfigurableScanner) { - s.SetDataFilesystem(f) + s.SetFrameworks(frameworks) } } @@ -113,15 +29,3 @@ func ScannerWithRegoOnly(regoOnly bool) ScannerOption { s.SetRegoOnly(regoOnly) } } - -func ScannerWithRegoErrorLimits(limit int) ScannerOption { - return func(s ConfigurableScanner) { - s.SetRegoErrorLimit(limit) - } -} - -func ScannerWithCustomSchemas(schemas map[string][]byte) ScannerOption { - return func(s ConfigurableScanner) { - s.SetCustomSchemas(schemas) - } -} diff --git a/pkg/iac/scanners/terraform/fs_test.go b/pkg/iac/scanners/terraform/fs_test.go index 649062792514..fb5448873607 100644 --- a/pkg/iac/scanners/terraform/fs_test.go +++ b/pkg/iac/scanners/terraform/fs_test.go @@ -8,13 +8,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" + "github.com/aquasecurity/trivy/pkg/iac/rego" ) func Test_OS_FS(t *testing.T) { s := New( - options.ScannerWithEmbeddedPolicies(true), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedPolicies(true), + rego.WithEmbeddedLibraries(true), ) results, err := s.ScanFS(context.TODO(), os.DirFS("testdata"), "fail") require.NoError(t, err) diff --git a/pkg/iac/scanners/terraform/ignore_test.go b/pkg/iac/scanners/terraform/ignore_test.go index 4a2cbce14a86..a42abc323d31 100644 --- a/pkg/iac/scanners/terraform/ignore_test.go +++ b/pkg/iac/scanners/terraform/ignore_test.go @@ -11,6 +11,7 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/providers" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/rules" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" @@ -956,11 +957,11 @@ deny[res] { }` localScanner := New( - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(true), options.ScannerWithRegoOnly(true), - options.ScannerWithPolicyNamespaces("user"), - options.ScannerWithPolicyReader(strings.NewReader(check)), + rego.WithPolicyNamespaces("user"), + rego.WithPolicyReader(strings.NewReader(check)), ScannerWithDownloadsAllowed(false), ScannerWithSkipCachedModules(true), ) diff --git a/pkg/iac/scanners/terraform/scanner.go b/pkg/iac/scanners/terraform/scanner.go index d01afb8d962e..d574acdb2c4a 100644 --- a/pkg/iac/scanners/terraform/scanner.go +++ b/pkg/iac/scanners/terraform/scanner.go @@ -3,7 +3,6 @@ package terraform import ( "context" "fmt" - "io" "io/fs" "path" "path/filepath" @@ -28,48 +27,27 @@ var _ options.ConfigurableScanner = (*Scanner)(nil) var _ ConfigurableTerraformScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - logger *log.Logger - options []options.ScannerOption - parserOpt []parser.Option - executorOpt []executor.Option - dirs map[string]struct{} - forceAllDirs bool - policyDirs []string - policyReaders []io.Reader - regoScanner *rego.Scanner - execLock sync.RWMutex - - frameworks []framework.Framework - spec string - loadEmbeddedLibraries bool - loadEmbeddedPolicies bool + mu sync.Mutex + logger *log.Logger + options []options.ScannerOption + parserOpt []parser.Option + executorOpt []executor.Option + dirs map[string]struct{} + forceAllDirs bool + regoScanner *rego.Scanner + execLock sync.RWMutex } func (s *Scanner) SetIncludeDeprecatedChecks(b bool) { s.executorOpt = append(s.executorOpt, executor.OptionWithIncludeDeprecatedChecks(b)) } -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - func (s *Scanner) SetRegoOnly(regoOnly bool) { s.executorOpt = append(s.executorOpt, executor.OptionWithRegoOnly(regoOnly)) } func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b + s.executorOpt = append(s.executorOpt, executor.OptionWithFrameworks(frameworks...)) } func (s *Scanner) Name() string { @@ -88,32 +66,6 @@ func (s *Scanner) AddExecutorOptions(opts ...executor.Option) { s.executorOpt = append(s.executorOpt, opts...) } -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) { -} - -func (s *Scanner) SetPerResultTracingEnabled(_ bool) { -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(_ ...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) {} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - func New(opts ...options.ScannerOption) *Scanner { s := &Scanner{ dirs: make(map[string]struct{}), @@ -133,7 +85,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { return s.regoScanner, nil } regoScanner := rego.NewScanner(types.SourceCloud, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner @@ -166,7 +118,7 @@ func (s *Scanner) ScanFS(ctx context.Context, target fs.FS, dir string) (scan.Re } s.execLock.Lock() - s.executorOpt = append(s.executorOpt, executor.OptionWithRegoScanner(regoScanner), executor.OptionWithFrameworks(s.frameworks...)) + s.executorOpt = append(s.executorOpt, executor.OptionWithRegoScanner(regoScanner)) s.execLock.Unlock() var allResults scan.Results diff --git a/pkg/iac/scanners/terraform/scanner_integration_test.go b/pkg/iac/scanners/terraform/scanner_integration_test.go index 098d6a91d450..96c681e97553 100644 --- a/pkg/iac/scanners/terraform/scanner_integration_test.go +++ b/pkg/iac/scanners/terraform/scanner_integration_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/aquasecurity/trivy/internal/testutil" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) @@ -44,10 +45,10 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyFilesystem(fs), - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(false), + rego.WithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), options.ScannerWithRegoOnly(true), ScannerWithAllDirectories(true), ScannerWithSkipCachedModules(true), @@ -101,10 +102,10 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyFilesystem(fs), - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(false), + rego.WithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), options.ScannerWithRegoOnly(true), ScannerWithAllDirectories(true), ScannerWithSkipCachedModules(true), @@ -147,10 +148,10 @@ deny[cause] { t.Run("without skip", func(t *testing.T) { scanner := New( ScannerWithSkipCachedModules(true), - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "test") require.NoError(t, err) @@ -163,10 +164,10 @@ deny[cause] { scanner := New( ScannerWithSkipDownloaded(true), ScannerWithSkipCachedModules(true), - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "test") require.NoError(t, err) @@ -217,10 +218,10 @@ deny[res] { scanner := New( ScannerWithSkipDownloaded(true), ScannerWithSkipCachedModules(true), - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(true), + rego.WithEmbeddedPolicies(false), ) results, err := scanner.ScanFS(context.TODO(), fs, "test") require.NoError(t, err) diff --git a/pkg/iac/scanners/terraform/scanner_test.go b/pkg/iac/scanners/terraform/scanner_test.go index cd1663ec0eda..39ee35e81321 100644 --- a/pkg/iac/scanners/terraform/scanner_test.go +++ b/pkg/iac/scanners/terraform/scanner_test.go @@ -11,6 +11,7 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/providers" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/rules" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" @@ -76,8 +77,8 @@ deny[cause] { }) scanner := New( - options.ScannerWithPolicyFilesystem(fs), - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), ) @@ -213,8 +214,8 @@ cause := bucket.name }) scanner := New( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyNamespaces(test.includedNamespaces...), + rego.WithPolicyDirs("rules"), + rego.WithPolicyNamespaces(test.includedNamespaces...), ) results, err := scanner.ScanFS(context.TODO(), fs, "code") @@ -270,7 +271,7 @@ deny[cause] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), ) @@ -318,9 +319,9 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "code") @@ -386,9 +387,9 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "code") @@ -470,9 +471,9 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "code") @@ -643,8 +644,8 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyFilesystem(fs), - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), ) @@ -718,11 +719,11 @@ bucket_name = "test" }) scanner := New( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), ScannerWithAllDirectories(true), ScannerWithTFVarsPaths("main.tfvars"), ScannerWithConfigsFileSystem(configsFS), @@ -752,11 +753,11 @@ bucket_name = "test" }) scanner := New( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), ScannerWithAllDirectories(true), ScannerWithTFVarsPaths("main.tfvars"), ScannerWithConfigsFileSystem(fs), @@ -845,10 +846,10 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyFilesystem(fs), - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(false), + rego.WithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), options.ScannerWithRegoOnly(true), ScannerWithAllDirectories(true), ) @@ -915,11 +916,11 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), ScannerWithAllDirectories(true), ) @@ -984,11 +985,11 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), ScannerWithAllDirectories(true), ) @@ -1048,13 +1049,13 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), options.ScannerWithRegoOnly(true), - options.ScannerWithPolicyNamespaces("user"), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithRegoErrorLimits(0), + rego.WithPolicyNamespaces("user"), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), + rego.WithRegoErrorLimits(0), ScannerWithAllDirectories(true), ) @@ -1089,9 +1090,9 @@ func TestSkipDeprecatedGoChecks(t *testing.T) { }) scanner := New( - options.ScannerWithPolicyFilesystem(fsys), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), + rego.WithPolicyFilesystem(fsys), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), ScannerWithAllDirectories(true), ) diff --git a/pkg/iac/scanners/terraform/setup_test.go b/pkg/iac/scanners/terraform/setup_test.go index d7a8f0277a96..5b98c438f9c1 100644 --- a/pkg/iac/scanners/terraform/setup_test.go +++ b/pkg/iac/scanners/terraform/setup_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" "github.com/aquasecurity/trivy/internal/testutil" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform/parser" @@ -39,7 +40,7 @@ func scanHCL(t *testing.T, source string, opts ...options.ScannerOption) scan.Re "main.tf": source, }) - localScanner := New(append(opts, options.ScannerWithEmbeddedPolicies(false))...) + localScanner := New(append(opts, rego.WithEmbeddedPolicies(false))...) results, err := localScanner.ScanFS(context.TODO(), fs, ".") require.NoError(t, err) return results @@ -51,7 +52,7 @@ func scanJSON(t *testing.T, source string) scan.Results { "main.tf.json": source, }) - s := New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + s := New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) results, err := s.ScanFS(context.TODO(), fs, ".") require.NoError(t, err) return results diff --git a/pkg/iac/scanners/terraformplan/snapshot/scanner_test.go b/pkg/iac/scanners/terraformplan/snapshot/scanner_test.go index c7ad3a3b4e0b..992bed5af809 100644 --- a/pkg/iac/scanners/terraformplan/snapshot/scanner_test.go +++ b/pkg/iac/scanners/terraformplan/snapshot/scanner_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" tfscanner "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform" @@ -19,12 +20,12 @@ import ( func initScanner(opts ...options.ScannerOption) *Scanner { defaultOpts := []options.ScannerOption{ - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithPolicyNamespaces("user"), - options.ScannerWithPolicyDirs("."), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(true), + rego.WithPolicyNamespaces("user"), + rego.WithPolicyDirs("."), options.ScannerWithRegoOnly(true), - options.ScannerWithRegoErrorLimits(0), + rego.WithRegoErrorLimits(0), tfscanner.ScannerWithSkipCachedModules(true), } @@ -59,7 +60,7 @@ func TestScanner_Scan(t *testing.T) { policyFS := os.DirFS(filepath.Join("testdata", tt.dir, "checks")) - s := initScanner(options.ScannerWithPolicyFilesystem(policyFS)) + s := initScanner(rego.WithPolicyFilesystem(policyFS)) result, err := s.Scan(context.TODO(), f) require.NoError(t, err) @@ -108,13 +109,13 @@ func Test_ScanFS(t *testing.T) { fs := os.DirFS("testdata") scanner := New( - options.ScannerWithPolicyDirs(path.Join(tc.dir, "checks")), - options.ScannerWithPolicyFilesystem(fs), + rego.WithPolicyDirs(path.Join(tc.dir, "checks")), + rego.WithPolicyFilesystem(fs), options.ScannerWithRegoOnly(true), - options.ScannerWithPolicyNamespaces("user"), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithRegoErrorLimits(0), + rego.WithPolicyNamespaces("user"), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), + rego.WithRegoErrorLimits(0), tfscanner.ScannerWithSkipCachedModules(true), ) diff --git a/pkg/iac/scanners/terraformplan/tfjson/scanner.go b/pkg/iac/scanners/terraformplan/tfjson/scanner.go index 8b16ecb43116..b3e8725c42ae 100644 --- a/pkg/iac/scanners/terraformplan/tfjson/scanner.go +++ b/pkg/iac/scanners/terraformplan/tfjson/scanner.go @@ -6,82 +6,20 @@ import ( "io" "io/fs" - "github.com/aquasecurity/trivy/pkg/iac/framework" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" - terraformScanner "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform" - "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform/executor" + "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform" "github.com/aquasecurity/trivy/pkg/iac/scanners/terraformplan/tfjson/parser" "github.com/aquasecurity/trivy/pkg/log" ) type Scanner struct { - parser *parser.Parser - logger *log.Logger - options []options.ScannerOption - spec string - executorOpt []executor.Option - frameworks []framework.Framework - loadEmbeddedPolicies bool - loadEmbeddedLibraries bool - enableEmbeddedLibraries bool - policyDirs []string - policyReaders []io.Reader + parser *parser.Parser + logger *log.Logger + options []options.ScannerOption + tfScanner *terraform.Scanner } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetRegoOnly(regoOnly bool) { - s.executorOpt = append(s.executorOpt, executor.OptionWithRegoOnly(regoOnly)) -} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetEmbeddedLibrariesEnabled(enabled bool) { - s.enableEmbeddedLibraries = enabled -} - -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) { -} - -func (s *Scanner) SetPerResultTracingEnabled(_ bool) { -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(_ ...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) {} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - func (s *Scanner) Name() string { return "Terraform Plan JSON" } @@ -117,12 +55,10 @@ func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (scan.Resu func New(opts ...options.ScannerOption) *Scanner { scanner := &Scanner{ - options: opts, - logger: log.WithPrefix("tfjson scanner"), - parser: parser.New(), - } - for _, o := range opts { - o(scanner) + options: opts, + logger: log.WithPrefix("tfjson scanner"), + parser: parser.New(), + tfScanner: terraform.New(opts...), } return scanner @@ -151,6 +87,5 @@ func (s *Scanner) Scan(reader io.Reader) (scan.Results, error) { return nil, fmt.Errorf("failed to convert plan to FS: %w", err) } - scanner := terraformScanner.New(s.options...) - return scanner.ScanFS(context.TODO(), planFS, ".") + return s.tfScanner.ScanFS(context.TODO(), planFS, ".") } diff --git a/pkg/iac/scanners/terraformplan/tfjson/scanner_test.go b/pkg/iac/scanners/terraformplan/tfjson/scanner_test.go index 289147f482dd..9173c8046bb1 100644 --- a/pkg/iac/scanners/terraformplan/tfjson/scanner_test.go +++ b/pkg/iac/scanners/terraformplan/tfjson/scanner_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/aquasecurity/trivy/internal/testutil" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) @@ -51,7 +52,7 @@ func Test_TerraformScanner(t *testing.T) { inputFile: "test/testdata/plan.json", check: defaultCheck, options: []options.ScannerOption{ - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), }, }, @@ -60,9 +61,9 @@ func Test_TerraformScanner(t *testing.T) { inputFile: "test/testdata/plan.json", check: defaultCheck, options: []options.ScannerOption{ - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithPolicyNamespaces("user"), + rego.WithPolicyNamespaces("user"), }, }, { @@ -90,9 +91,9 @@ deny[cause] { } `, options: []options.ScannerOption{ - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithPolicyNamespaces("user"), + rego.WithPolicyNamespaces("user"), }, }, { @@ -100,9 +101,9 @@ deny[cause] { inputFile: "test/testdata/arbitrary_name.json", check: defaultCheck, options: []options.ScannerOption{ - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithPolicyNamespaces("user"), + rego.WithPolicyNamespaces("user"), }, }, } @@ -115,7 +116,7 @@ deny[cause] { "/rules/test.rego": tc.check, }) - so := append(tc.options, options.ScannerWithPolicyFilesystem(fs)) + so := append(tc.options, rego.WithPolicyFilesystem(fs)) scanner := New(so...) results, err := scanner.ScanFS(context.TODO(), fs, "code") diff --git a/pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go b/pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go index dd77c2d89f6e..1c0ac8234862 100644 --- a/pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go +++ b/pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go @@ -8,15 +8,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" "github.com/aquasecurity/trivy/pkg/iac/scanners/terraformplan/tfjson" ) func Test_Scanning_Plan(t *testing.T) { scanner := tfjson.New( - options.ScannerWithEmbeddedPolicies(true), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedPolicies(true), + rego.WithEmbeddedLibraries(true), ) b, _ := os.ReadFile("testdata/plan.json") testFS := fstest.MapFS{ diff --git a/pkg/iac/scanners/toml/scanner.go b/pkg/iac/scanners/toml/scanner.go index 235cc65dada5..216d0b1f9697 100644 --- a/pkg/iac/scanners/toml/scanner.go +++ b/pkg/iac/scanners/toml/scanner.go @@ -2,7 +2,6 @@ package toml import ( "context" - "io" "io/fs" "sync" @@ -18,67 +17,21 @@ import ( var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - logger *log.Logger - options []options.ScannerOption - policyDirs []string - policyReaders []io.Reader - parser *parser.Parser - regoScanner *rego.Scanner - frameworks []framework.Framework - spec string - loadEmbeddedPolicies bool - loadEmbeddedLibraries bool + mu sync.Mutex + logger *log.Logger + options []options.ScannerOption + parser *parser.Parser + regoScanner *rego.Scanner } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetRegoOnly(bool) {} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} +func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} +func (s *Scanner) SetRegoOnly(bool) {} +func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} func (s *Scanner) Name() string { return "TOML" } -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) {} -func (s *Scanner) SetPerResultTracingEnabled(_ bool) {} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(_ ...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) {} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - func NewScanner(opts ...options.ScannerOption) *Scanner { s := &Scanner{ options: opts, @@ -137,7 +90,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { return s.regoScanner, nil } regoScanner := rego.NewScanner(types.SourceTOML, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/toml/scanner_test.go b/pkg/iac/scanners/toml/scanner_test.go index d3c4e51e3b63..ea5819448288 100644 --- a/pkg/iac/scanners/toml/scanner_test.go +++ b/pkg/iac/scanners/toml/scanner_test.go @@ -9,8 +9,8 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) func Test_BasicScan(t *testing.T) { @@ -52,7 +52,7 @@ deny[res] { `, }) - scanner := NewScanner(options.ScannerWithPolicyDirs("rules")) + scanner := NewScanner(rego.WithPolicyDirs("rules")) results, err := scanner.ScanFS(context.TODO(), fs, "code") require.NoError(t, err) diff --git a/pkg/iac/scanners/yaml/scanner.go b/pkg/iac/scanners/yaml/scanner.go index 67b661ee5971..565d10df1f83 100644 --- a/pkg/iac/scanners/yaml/scanner.go +++ b/pkg/iac/scanners/yaml/scanner.go @@ -2,7 +2,6 @@ package yaml import ( "context" - "io" "io/fs" "sync" @@ -18,66 +17,21 @@ import ( var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - options []options.ScannerOption - logger *log.Logger - policyDirs []string - policyReaders []io.Reader - parser *parser.Parser - regoScanner *rego.Scanner - frameworks []framework.Framework - spec string - loadEmbeddedLibraries bool - loadEmbeddedPolicies bool + mu sync.Mutex + options []options.ScannerOption + logger *log.Logger + parser *parser.Parser + regoScanner *rego.Scanner } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetRegoOnly(bool) {} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} +func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} +func (s *Scanner) SetRegoOnly(bool) {} +func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} func (s *Scanner) Name() string { return "YAML" } -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) {} -func (s *Scanner) SetPerResultTracingEnabled(_ bool) {} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(_ ...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) {} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - func NewScanner(opts ...options.ScannerOption) *Scanner { s := &Scanner{ options: opts, @@ -138,7 +92,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { return s.regoScanner, nil } regoScanner := rego.NewScanner(types.SourceYAML, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/yaml/scanner_test.go b/pkg/iac/scanners/yaml/scanner_test.go index 02468158fcf9..b7c4ec623887 100644 --- a/pkg/iac/scanners/yaml/scanner_test.go +++ b/pkg/iac/scanners/yaml/scanner_test.go @@ -9,8 +9,8 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) func Test_BasicScan(t *testing.T) { @@ -55,7 +55,7 @@ deny[res] { `, }) - scanner := NewScanner(options.ScannerWithPolicyDirs("rules")) + scanner := NewScanner(rego.WithPolicyDirs("rules")) results, err := scanner.ScanFS(context.TODO(), fs, "code") require.NoError(t, err) diff --git a/pkg/misconf/scanner.go b/pkg/misconf/scanner.go index 2e979caba5e9..db203364a3e4 100644 --- a/pkg/misconf/scanner.go +++ b/pkg/misconf/scanner.go @@ -17,6 +17,7 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/iac/detection" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners" "github.com/aquasecurity/trivy/pkg/iac/scanners/azure/arm" @@ -208,8 +209,8 @@ func (s *Scanner) filterFS(fsys fs.FS) (fs.FS, error) { func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerOption, error) { opts := []options.ScannerOption{ - options.ScannerWithEmbeddedPolicies(!opt.DisableEmbeddedPolicies), - options.ScannerWithEmbeddedLibraries(!opt.DisableEmbeddedLibraries), + rego.WithEmbeddedPolicies(!opt.DisableEmbeddedPolicies), + rego.WithEmbeddedLibraries(!opt.DisableEmbeddedLibraries), options.ScannerWithIncludeDeprecatedChecks(opt.IncludeDeprecatedChecks), } @@ -218,7 +219,7 @@ func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerO return nil, err } if policyFS != nil { - opts = append(opts, options.ScannerWithPolicyFilesystem(policyFS)) + opts = append(opts, rego.WithPolicyFilesystem(policyFS)) } dataFS, dataPaths, err := CreateDataFS(opt.DataPaths, opt.K8sVersion) @@ -231,13 +232,13 @@ func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerO }) opts = append(opts, - options.ScannerWithDataDirs(dataPaths...), - options.ScannerWithDataFilesystem(dataFS), - options.ScannerWithCustomSchemas(schemas), + rego.WithDataDirs(dataPaths...), + rego.WithDataFilesystem(dataFS), + rego.WithCustomSchemas(schemas), ) if opt.Trace { - opts = append(opts, options.ScannerWithPerResultTracing(true)) + opts = append(opts, rego.WithPerResultTracing(true)) } if opt.RegoOnly { @@ -245,15 +246,15 @@ func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerO } if len(policyPaths) > 0 { - opts = append(opts, options.ScannerWithPolicyDirs(policyPaths...)) + opts = append(opts, rego.WithPolicyDirs(policyPaths...)) } if len(opt.DataPaths) > 0 { - opts = append(opts, options.ScannerWithDataDirs(opt.DataPaths...)) + opts = append(opts, rego.WithDataDirs(opt.DataPaths...)) } if len(opt.Namespaces) > 0 { - opts = append(opts, options.ScannerWithPolicyNamespaces(opt.Namespaces...)) + opts = append(opts, rego.WithPolicyNamespaces(opt.Namespaces...)) } switch t { From 5dd94ebc1ffe3f1df511dee6381f92a5daefadf2 Mon Sep 17 00:00:00 2001 From: afdesk Date: Thu, 19 Sep 2024 11:17:42 +0600 Subject: [PATCH 04/94] fix(sbom): export bom-ref when converting a package to a component (#7340) Signed-off-by: knqyf263 Co-authored-by: amf Co-authored-by: knqyf263 --- integration/integration_test.go | 1 - integration/sbom_test.go | 12 + ...d-multiple-lockfiles-short.cdx.json.golden | 526 ++++++++++++++++++ pkg/sbom/cyclonedx/marshal_test.go | 4 +- pkg/sbom/cyclonedx/unmarshal.go | 17 +- pkg/sbom/io/encode.go | 26 +- 6 files changed, 571 insertions(+), 15 deletions(-) create mode 100644 integration/testdata/fluentd-multiple-lockfiles-short.cdx.json.golden diff --git a/integration/integration_test.go b/integration/integration_test.go index c263ec2fc51e..96c8f54a67e9 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -186,7 +186,6 @@ func readCycloneDX(t *testing.T, filePath string) *cdx.BOM { return (*bom.Components)[i].Name < (*bom.Components)[j].Name }) for i := range *bom.Components { - (*bom.Components)[i].BOMRef = "" sort.Slice(*(*bom.Components)[i].Properties, func(ii, jj int) bool { return (*(*bom.Components)[i].Properties)[ii].Name < (*(*bom.Components)[i].Properties)[jj].Name }) diff --git a/integration/sbom_test.go b/integration/sbom_test.go index e3ee5b89cc3d..e887f1520e68 100644 --- a/integration/sbom_test.go +++ b/integration/sbom_test.go @@ -25,6 +25,7 @@ func TestSBOM(t *testing.T) { name string args args golden string + fakeUUID string override OverrideFunc }{ { @@ -57,6 +58,16 @@ func TestSBOM(t *testing.T) { }, golden: "testdata/fluentd-multiple-lockfiles.json.golden", }, + { + name: "scan SBOM into SBOM", + args: args{ + input: "testdata/fixtures/sbom/fluentd-multiple-lockfiles-cyclonedx.json", + format: "cyclonedx", + artifactType: "cyclonedx", + }, + fakeUUID: "3ff14136-e09f-4df9-80ea-%012d", + golden: "testdata/fluentd-multiple-lockfiles-short.cdx.json.golden", + }, { name: "minikube KBOM", args: args{ @@ -165,6 +176,7 @@ func TestSBOM(t *testing.T) { // Run "trivy sbom" runTest(t, osArgs, tt.golden, outputFile, types.Format(tt.args.format), runOptions{ override: overrideFuncs(overrideSBOMReport, overrideUID, tt.override), + fakeUUID: tt.fakeUUID, }) }) } diff --git a/integration/testdata/fluentd-multiple-lockfiles-short.cdx.json.golden b/integration/testdata/fluentd-multiple-lockfiles-short.cdx.json.golden new file mode 100644 index 000000000000..496ca8ae3110 --- /dev/null +++ b/integration/testdata/fluentd-multiple-lockfiles-short.cdx.json.golden @@ -0,0 +1,526 @@ +{ + "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.6", + "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000010", + "version": 1, + "metadata": { + "timestamp": "2021-08-25T12:20:30+00:00", + "tools": { + "components": [ + { + "type": "application", + "group": "aquasecurity", + "name": "trivy", + "version": "dev" + } + ] + }, + "component": { + "bom-ref": "95de56ee-980c-413d-8f68-6c674dc3e9d1", + "type": "container", + "name": "integration/testdata/fixtures/images/fluentd-multiple-lockfiles.tar.gz", + "properties": [ + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:02874b2b269dea8dde0f7edb4c9906904dfe38a09de1a214f20c650cfb15c60e" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:25165eb51d15842f870f97873e0a58409d5e860e6108e3dd829bd10e484c0065" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:3752e1f6fd759c795c13aff2c93c081529366e27635ba6621e849b0f9cfc77f0" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:75e43d55939745950bc3f8fad56c5834617c4339f0f54755e69a0dd5372624e9" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:788c00e2cfc8f2a018ae4344ccf0b2c226ebd756d7effd1ce50eea1a4252cd89" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:831c5620387fb9efec59fc82a42b948546c6be601e3ab34a87108ecf852aa15f" + }, + { + "name": "aquasecurity:trivy:ImageID", + "value": "sha256:5a992077baba51b97f27591a10d54d2f2723dc9c81a3fe419e261023f2554933" + }, + { + "name": "aquasecurity:trivy:SchemaVersion", + "value": "2" + } + ] + } + }, + "components": [ + { + "bom-ref": "353f2470-9c8b-4647-9d0d-96d893838dc8", + "type": "operating-system", + "name": "debian", + "version": "10.2", + "properties": [ + { + "name": "aquasecurity:trivy:Class", + "value": "os-pkgs" + }, + { + "name": "aquasecurity:trivy:Type", + "value": "debian" + } + ] + }, + { + "bom-ref": "pkg:deb/debian/bash@5.0-4?distro=debian-10.2", + "type": "library", + "name": "bash", + "version": "5.0-4", + "purl": "pkg:deb/debian/bash@5.0-4?distro=debian-10.2", + "properties": [ + { + "name": "aquasecurity:trivy:PkgID", + "value": "bash@5.0-4" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "debian" + }, + { + "name": "aquasecurity:trivy:SrcName", + "value": "bash" + }, + { + "name": "aquasecurity:trivy:SrcVersion", + "value": "5.0-4" + } + ] + }, + { + "bom-ref": "pkg:deb/debian/libidn2-0@2.0.5-1?distro=debian-10.2", + "type": "library", + "name": "libidn2-0", + "version": "2.0.5-1", + "purl": "pkg:deb/debian/libidn2-0@2.0.5-1?distro=debian-10.2", + "properties": [ + { + "name": "aquasecurity:trivy:PkgID", + "value": "libidn2-0@2.0.5-1" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "debian" + }, + { + "name": "aquasecurity:trivy:SrcName", + "value": "libidn2" + }, + { + "name": "aquasecurity:trivy:SrcVersion", + "value": "2.0.5-1" + } + ] + }, + { + "bom-ref": "pkg:gem/activesupport@6.0.2.1?file_path=var%2Flib%2Fgems%2F2.5.0%2Fspecifications%2Factivesupport-6.0.2.1.gemspec", + "type": "library", + "name": "activesupport", + "version": "6.0.2.1", + "licenses": [ + { + "license": { + "name": "MIT" + } + } + ], + "purl": "pkg:gem/activesupport@6.0.2.1", + "properties": [ + { + "name": "aquasecurity:trivy:FilePath", + "value": "var/lib/gems/2.5.0/specifications/activesupport-6.0.2.1.gemspec" + }, + { + "name": "aquasecurity:trivy:PkgID", + "value": "activesupport@6.0.2.1" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "gemspec" + } + ] + } + ], + "dependencies": [ + { + "ref": "353f2470-9c8b-4647-9d0d-96d893838dc8", + "dependsOn": [ + "pkg:deb/debian/bash@5.0-4?distro=debian-10.2", + "pkg:deb/debian/libidn2-0@2.0.5-1?distro=debian-10.2" + ] + }, + { + "ref": "95de56ee-980c-413d-8f68-6c674dc3e9d1", + "dependsOn": [ + "353f2470-9c8b-4647-9d0d-96d893838dc8", + "pkg:gem/activesupport@6.0.2.1?file_path=var%2Flib%2Fgems%2F2.5.0%2Fspecifications%2Factivesupport-6.0.2.1.gemspec" + ] + }, + { + "ref": "pkg:deb/debian/bash@5.0-4?distro=debian-10.2", + "dependsOn": [] + }, + { + "ref": "pkg:deb/debian/libidn2-0@2.0.5-1?distro=debian-10.2", + "dependsOn": [] + }, + { + "ref": "pkg:gem/activesupport@6.0.2.1?file_path=var%2Flib%2Fgems%2F2.5.0%2Fspecifications%2Factivesupport-6.0.2.1.gemspec", + "dependsOn": [] + } + ], + "vulnerabilities": [ + { + "id": "CVE-2019-18224", + "source": { + "name": "debian", + "url": "https://salsa.debian.org/security-tracker-team/security-tracker" + }, + "ratings": [ + { + "source": { + "name": "amazon" + }, + "severity": "medium" + }, + { + "source": { + "name": "nvd" + }, + "score": 7.5, + "severity": "high", + "method": "CVSSv2", + "vector": "AV:N/AC:L/Au:N/C:P/I:P/A:P" + }, + { + "source": { + "name": "nvd" + }, + "score": 9.8, + "severity": "critical", + "method": "CVSSv31", + "vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" + }, + { + "source": { + "name": "redhat" + }, + "score": 5.6, + "severity": "medium", + "method": "CVSSv3", + "vector": "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L" + }, + { + "source": { + "name": "ubuntu" + }, + "severity": "medium" + } + ], + "cwes": [ + 787 + ], + "description": "idn2_to_ascii_4i in lib/lookup.c in GNU libidn2 before 2.1.1 has a heap-based buffer overflow via a long domain string.", + "recommendation": "Upgrade libidn2-0 to version 2.0.5-1+deb10u1", + "advisories": [ + { + "url": "https://avd.aquasec.com/nvd/cve-2019-18224" + }, + { + "url": "http://lists.opensuse.org/opensuse-security-announce/2019-12/msg00008.html" + }, + { + "url": "http://lists.opensuse.org/opensuse-security-announce/2019-12/msg00009.html" + }, + { + "url": "https://access.redhat.com/security/cve/CVE-2019-18224" + }, + { + "url": "https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12420" + }, + { + "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18224" + }, + { + "url": "https://github.com/libidn/libidn2/commit/e4d1558aa2c1c04a05066ee8600f37603890ba8c" + }, + { + "url": "https://github.com/libidn/libidn2/compare/libidn2-2.1.0...libidn2-2.1.1" + }, + { + "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/JDQVQ2XPV5BTZUFINT7AFJSKNNBVURNJ/" + }, + { + "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/MINU5RKDFE6TKAFY5DRFN3WSFDS4DYVS/" + }, + { + "url": "https://seclists.org/bugtraq/2020/Feb/4" + }, + { + "url": "https://security.gentoo.org/glsa/202003-63" + }, + { + "url": "https://ubuntu.com/security/notices/USN-4168-1" + }, + { + "url": "https://usn.ubuntu.com/4168-1/" + }, + { + "url": "https://www.debian.org/security/2020/dsa-4613" + } + ], + "published": "2019-10-21T17:15:00+00:00", + "updated": "2019-10-29T19:15:00+00:00", + "affects": [ + { + "ref": "pkg:deb/debian/libidn2-0@2.0.5-1?distro=debian-10.2", + "versions": [ + { + "version": "2.0.5-1", + "status": "affected" + } + ] + } + ] + }, + { + "id": "CVE-2019-18276", + "source": { + "name": "debian", + "url": "https://salsa.debian.org/security-tracker-team/security-tracker" + }, + "ratings": [ + { + "source": { + "name": "cbl-mariner" + }, + "severity": "high" + }, + { + "source": { + "name": "debian" + }, + "severity": "low" + }, + { + "source": { + "name": "nvd" + }, + "score": 7.2, + "severity": "high", + "method": "CVSSv2", + "vector": "AV:L/AC:L/Au:N/C:C/I:C/A:C" + }, + { + "source": { + "name": "nvd" + }, + "score": 7.8, + "severity": "high", + "method": "CVSSv31", + "vector": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H" + }, + { + "source": { + "name": "oracle-oval" + }, + "severity": "low" + }, + { + "source": { + "name": "photon" + }, + "severity": "high" + }, + { + "source": { + "name": "redhat" + }, + "score": 7.8, + "severity": "low", + "method": "CVSSv31", + "vector": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H" + }, + { + "source": { + "name": "ubuntu" + }, + "severity": "low" + } + ], + "cwes": [ + 273 + ], + "description": "An issue was discovered in disable_priv_mode in shell.c in GNU Bash through 5.0 patch 11. By default, if Bash is run with its effective UID not equal to its real UID, it will drop privileges by setting its effective UID to its real UID. However, it does so incorrectly. On Linux and other systems that support \"saved UID\" functionality, the saved UID is not dropped. An attacker with command execution in the shell can use \"enable -f\" for runtime loading of a new builtin, which can be a shared object that calls setuid() and therefore regains privileges. However, binaries running with an effective UID of 0 are unaffected.", + "advisories": [ + { + "url": "https://avd.aquasec.com/nvd/cve-2019-18276" + }, + { + "url": "http://packetstormsecurity.com/files/155498/Bash-5.0-Patch-11-Privilege-Escalation.html" + }, + { + "url": "https://access.redhat.com/security/cve/CVE-2019-18276" + }, + { + "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18276" + }, + { + "url": "https://github.com/bminor/bash/commit/951bdaad7a18cc0dc1036bba86b18b90874d39ff" + }, + { + "url": "https://linux.oracle.com/cve/CVE-2019-18276.html" + }, + { + "url": "https://linux.oracle.com/errata/ELSA-2021-1679.html" + }, + { + "url": "https://lists.apache.org/thread.html/rf9fa47ab66495c78bb4120b0754dd9531ca2ff0430f6685ac9b07772@%3Cdev.mina.apache.org%3E" + }, + { + "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-18276" + }, + { + "url": "https://security.gentoo.org/glsa/202105-34" + }, + { + "url": "https://security.netapp.com/advisory/ntap-20200430-0003/" + }, + { + "url": "https://www.youtube.com/watch?v=-wGtxJ8opa8" + } + ], + "published": "2019-11-28T01:15:00+00:00", + "updated": "2021-05-26T12:15:00+00:00", + "affects": [ + { + "ref": "pkg:deb/debian/bash@5.0-4?distro=debian-10.2", + "versions": [ + { + "version": "5.0-4", + "status": "affected" + } + ] + } + ] + }, + { + "id": "CVE-2020-8165", + "source": { + "name": "ghsa", + "url": "https://github.com/advisories?query=type%3Areviewed+ecosystem%3Arubygems" + }, + "ratings": [ + { + "source": { + "name": "ghsa" + }, + "severity": "high" + }, + { + "source": { + "name": "nvd" + }, + "score": 7.5, + "severity": "high", + "method": "CVSSv2", + "vector": "AV:N/AC:L/Au:N/C:P/I:P/A:P" + }, + { + "source": { + "name": "nvd" + }, + "score": 9.8, + "severity": "critical", + "method": "CVSSv31", + "vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" + }, + { + "source": { + "name": "redhat" + }, + "score": 9.8, + "severity": "high", + "method": "CVSSv31", + "vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" + } + ], + "cwes": [ + 502 + ], + "description": "A deserialization of untrusted data vulnerability exists in rails < 5.2.4.3, rails < 6.0.3.1 that can allow an attacker to unmarshal user-provided objects in MemCacheStore and RedisCacheStore potentially resulting in an RCE.", + "recommendation": "Upgrade activesupport to version 6.0.3.1, 5.2.4.3", + "advisories": [ + { + "url": "https://avd.aquasec.com/nvd/cve-2020-8165" + }, + { + "url": "http://lists.opensuse.org/opensuse-security-announce/2020-10/msg00031.html" + }, + { + "url": "http://lists.opensuse.org/opensuse-security-announce/2020-10/msg00034.html" + }, + { + "url": "https://access.redhat.com/security/cve/CVE-2020-8165" + }, + { + "url": "https://github.com/advisories/GHSA-2p68-f74v-9wc6" + }, + { + "url": "https://github.com/rubysec/ruby-advisory-db/blob/master/gems/activesupport/CVE-2020-8165.yml" + }, + { + "url": "https://groups.google.com/forum/#!msg/rubyonrails-security/bv6fW4S0Y1c/KnkEqM7AAQAJ" + }, + { + "url": "https://groups.google.com/forum/#!topic/rubyonrails-security/bv6fW4S0Y1c" + }, + { + "url": "https://groups.google.com/g/rubyonrails-security/c/bv6fW4S0Y1c" + }, + { + "url": "https://hackerone.com/reports/413388" + }, + { + "url": "https://lists.debian.org/debian-lts-announce/2020/06/msg00022.html" + }, + { + "url": "https://lists.debian.org/debian-lts-announce/2020/07/msg00013.html" + }, + { + "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-8165" + }, + { + "url": "https://weblog.rubyonrails.org/2020/5/18/Rails-5-2-4-3-and-6-0-3-1-have-been-released/" + }, + { + "url": "https://www.debian.org/security/2020/dsa-4766" + } + ], + "published": "2020-06-19T18:15:00+00:00", + "updated": "2020-10-17T12:15:00+00:00", + "affects": [ + { + "ref": "pkg:gem/activesupport@6.0.2.1?file_path=var%2Flib%2Fgems%2F2.5.0%2Fspecifications%2Factivesupport-6.0.2.1.gemspec", + "versions": [ + { + "version": "6.0.2.1", + "status": "affected" + } + ] + } + ] + } + ] +} diff --git a/pkg/sbom/cyclonedx/marshal_test.go b/pkg/sbom/cyclonedx/marshal_test.go index e778b803619c..8b88c4ec762a 100644 --- a/pkg/sbom/cyclonedx/marshal_test.go +++ b/pkg/sbom/cyclonedx/marshal_test.go @@ -1462,7 +1462,7 @@ func TestMarshaler_MarshalReport(t *testing.T) { Name: "com.fasterxml.jackson.core:jackson-databind", Version: "2.13.4.1", Identifier: ftypes.PkgIdentifier{ - BOMRef: "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4.1?file_path=jackson-databind-2.13.4.1.jar", + BOMRef: "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4.1", UID: "9A5066570222D04C", PURL: &packageurl.PackageURL{ Type: packageurl.TypeMaven, @@ -1480,7 +1480,7 @@ func TestMarshaler_MarshalReport(t *testing.T) { PkgName: "com.fasterxml.jackson.core:jackson-databind", PkgPath: "jackson-databind-2.13.4.1.jar", PkgIdentifier: ftypes.PkgIdentifier{ - BOMRef: "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4.1?file_path=jackson-databind-2.13.4.1.jar", + BOMRef: "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4.1", UID: "9A5066570222D04C", PURL: &packageurl.PackageURL{ Type: packageurl.TypeMaven, diff --git a/pkg/sbom/cyclonedx/unmarshal.go b/pkg/sbom/cyclonedx/unmarshal.go index de410d008794..2a2456063670 100644 --- a/pkg/sbom/cyclonedx/unmarshal.go +++ b/pkg/sbom/cyclonedx/unmarshal.go @@ -128,13 +128,17 @@ func (b *BOM) parseComponent(c cdx.Component) (*core.Component, error) { return nil, xerrors.Errorf("failed to unmarshal component type: %w", err) } + identifier := ftypes.PkgIdentifier{ + BOMRef: c.BOMRef, + } + // Parse PURL - var purl packageurl.PackageURL if c.PackageURL != "" { - purl, err = packageurl.FromString(c.PackageURL) + purl, err := packageurl.FromString(c.PackageURL) if err != nil { return nil, xerrors.Errorf("failed to parse PURL: %w", err) } + identifier.PURL = &purl } component := &core.Component{ @@ -148,12 +152,9 @@ func (b *BOM) parseComponent(c cdx.Component) (*core.Component, error) { Digests: b.unmarshalHashes(c.Hashes), }, }, - PkgIdentifier: ftypes.PkgIdentifier{ - PURL: &purl, - BOMRef: c.BOMRef, - }, - Supplier: b.unmarshalSupplier(c.Supplier), - Properties: b.unmarshalProperties(c.Properties), + PkgIdentifier: identifier, + Supplier: b.unmarshalSupplier(c.Supplier), + Properties: b.unmarshalProperties(c.Properties), } return component, nil diff --git a/pkg/sbom/io/encode.go b/pkg/sbom/io/encode.go index 0be0bf361280..975b98d40b10 100644 --- a/pkg/sbom/io/encode.go +++ b/pkg/sbom/io/encode.go @@ -5,6 +5,7 @@ import ( "slices" "strconv" + "github.com/google/uuid" "github.com/package-url/packageurl-go" "github.com/samber/lo" "golang.org/x/xerrors" @@ -19,8 +20,9 @@ import ( ) type Encoder struct { - bom *core.BOM - opts core.Options + bom *core.BOM + opts core.Options + components map[uuid.UUID]*core.Component } func NewEncoder(opts core.Options) *Encoder { @@ -28,6 +30,9 @@ func NewEncoder(opts core.Options) *Encoder { } func (e *Encoder) Encode(report types.Report) (*core.BOM, error) { + if report.BOM != nil { + e.components = report.BOM.Components() + } // Metadata component root, err := e.rootComponent(report) if err != nil { @@ -257,6 +262,16 @@ func (e *Encoder) encodePackages(parent *core.Component, result types.Result) { } } +// existedPkgIdentifier tries to look for package identifier (BOM-ref, PURL) by component name and component type +func (e *Encoder) existedPkgIdentifier(name string, componentType core.ComponentType) ftypes.PkgIdentifier { + for _, c := range e.components { + if c.Name == name && c.Type == componentType { + return c.PkgIdentifier + } + } + return ftypes.PkgIdentifier{} +} + func (e *Encoder) resultComponent(root *core.Component, r types.Result, osFound *ftypes.OS) *core.Component { component := &core.Component{ Name: r.Target, @@ -279,8 +294,10 @@ func (e *Encoder) resultComponent(root *core.Component, r types.Result, osFound component.Version = osFound.Name } component.Type = core.TypeOS + component.PkgIdentifier = e.existedPkgIdentifier(component.Name, component.Type) case types.ClassLangPkg: component.Type = core.TypeApplication + component.PkgIdentifier = e.existedPkgIdentifier(component.Name, component.Type) } e.bom.AddRelationship(root, component, core.RelationshipContains) @@ -377,8 +394,9 @@ func (*Encoder) component(result types.Result, pkg ftypes.Package) *core.Compone SrcVersion: utils.FormatSrcVersion(pkg), SrcFile: srcFile, PkgIdentifier: ftypes.PkgIdentifier{ - UID: pkg.Identifier.UID, - PURL: pkg.Identifier.PURL, + UID: pkg.Identifier.UID, + PURL: pkg.Identifier.PURL, + BOMRef: pkg.Identifier.BOMRef, }, Supplier: pkg.Maintainer, Licenses: pkg.Licenses, From 1f9fc13da4a1e7c76c978e4f8e119bfd61a0480e Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Fri, 20 Sep 2024 10:50:12 +0600 Subject: [PATCH 05/94] perf(misconf): use port ranges instead of enumeration (#7549) Signed-off-by: nikpivkin --- .../terraform/google/compute/adapt_test.go | 4 +- .../terraform/google/compute/networks.go | 39 +++++++++++-------- .../terraform/google/compute/networks_test.go | 18 +++++++-- pkg/iac/providers/google/compute/firewall.go | 8 +++- pkg/iac/rego/schemas/cloud.json | 39 ++++++++++++++++++- 5 files changed, 84 insertions(+), 24 deletions(-) diff --git a/pkg/iac/adapters/terraform/google/compute/adapt_test.go b/pkg/iac/adapters/terraform/google/compute/adapt_test.go index a90c4315364a..d5bbe5a8f566 100644 --- a/pkg/iac/adapters/terraform/google/compute/adapt_test.go +++ b/pkg/iac/adapters/terraform/google/compute/adapt_test.go @@ -184,8 +184,8 @@ func TestLines(t *testing.T) { assert.Equal(t, 59, network.Firewall.IngressRules[0].Protocol.GetMetadata().Range().GetStartLine()) assert.Equal(t, 59, network.Firewall.IngressRules[0].Protocol.GetMetadata().Range().GetEndLine()) - assert.Equal(t, 60, network.Firewall.IngressRules[0].Ports[0].GetMetadata().Range().GetStartLine()) - assert.Equal(t, 60, network.Firewall.IngressRules[0].Ports[0].GetMetadata().Range().GetEndLine()) + assert.Equal(t, 60, network.Firewall.IngressRules[0].Ports[0].Metadata.Range().GetStartLine()) + assert.Equal(t, 60, network.Firewall.IngressRules[0].Ports[0].Metadata.Range().GetEndLine()) assert.Equal(t, 64, network.Subnetworks[0].Metadata.Range().GetStartLine()) assert.Equal(t, 72, network.Subnetworks[0].Metadata.Range().GetEndLine()) diff --git a/pkg/iac/adapters/terraform/google/compute/networks.go b/pkg/iac/adapters/terraform/google/compute/networks.go index ea3c9cb97a5f..5ea8753d1f7f 100644 --- a/pkg/iac/adapters/terraform/google/compute/networks.go +++ b/pkg/iac/adapters/terraform/google/compute/networks.go @@ -105,44 +105,51 @@ func adaptNetworks(modules terraform.Modules) (networks []compute.Network) { return networks } -func expandRange(ports string, attr *terraform.Attribute) []iacTypes.IntValue { +func expandRange(ports string, meta iacTypes.Metadata) (compute.PortRange, bool) { ports = strings.ReplaceAll(ports, " ", "") if !strings.Contains(ports, "-") { i, err := strconv.Atoi(ports) if err != nil { - return nil - } - return []iacTypes.IntValue{ - iacTypes.Int(i, attr.GetMetadata()), + return compute.PortRange{}, false } + return compute.PortRange{ + Metadata: meta, + Start: iacTypes.Int(i, meta), + End: iacTypes.Int(i, meta), + }, true } parts := strings.Split(ports, "-") if len(parts) != 2 { - return nil + return compute.PortRange{}, false } start, err := strconv.Atoi(parts[0]) if err != nil { - return nil + return compute.PortRange{}, false } end, err := strconv.Atoi(parts[1]) if err != nil { - return nil - } - var output []iacTypes.IntValue - for i := start; i <= end; i++ { - output = append(output, iacTypes.Int(i, attr.GetMetadata())) + return compute.PortRange{}, false } - return output + + return compute.PortRange{ + Metadata: meta, + Start: iacTypes.Int(start, meta), + End: iacTypes.Int(end, meta), + }, true } func adaptFirewallRule(firewall *compute.Firewall, firewallBlock, ruleBlock *terraform.Block, allow bool) { protocolAttr := ruleBlock.GetAttribute("protocol") portsAttr := ruleBlock.GetAttribute("ports") - var ports []iacTypes.IntValue + var rngs []compute.PortRange rawPorts := portsAttr.AsStringValues() for _, portStr := range rawPorts { - ports = append(ports, expandRange(portStr.Value(), portsAttr)...) + rng, ok := expandRange(portStr.Value(), portsAttr.GetMetadata()) + if !ok { + continue + } + rngs = append(rngs, rng) } // ingress by default @@ -153,7 +160,7 @@ func adaptFirewallRule(firewall *compute.Firewall, firewallBlock, ruleBlock *ter Enforced: iacTypes.BoolDefault(true, firewallBlock.GetMetadata()), IsAllow: iacTypes.Bool(allow, ruleBlock.GetMetadata()), Protocol: protocolAttr.AsStringValueOrDefault("tcp", ruleBlock), - Ports: ports, + Ports: rngs, } disabledAttr := firewallBlock.GetAttribute("disabled") diff --git a/pkg/iac/adapters/terraform/google/compute/networks_test.go b/pkg/iac/adapters/terraform/google/compute/networks_test.go index 32ad00bc5334..df1cef261e7d 100644 --- a/pkg/iac/adapters/terraform/google/compute/networks_test.go +++ b/pkg/iac/adapters/terraform/google/compute/networks_test.go @@ -39,7 +39,7 @@ func Test_adaptNetworks(t *testing.T) { source_ranges = ["1.2.3.4/32"] allow { protocol = "icmp" - ports = ["80", "8080"] + ports = ["80", "8080", "9090-9095"] } } `, @@ -57,9 +57,19 @@ func Test_adaptNetworks(t *testing.T) { IsAllow: iacTypes.Bool(true, iacTypes.NewTestMetadata()), Protocol: iacTypes.String("icmp", iacTypes.NewTestMetadata()), Enforced: iacTypes.Bool(true, iacTypes.NewTestMetadata()), - Ports: []iacTypes.IntValue{ - iacTypes.Int(80, iacTypes.NewTestMetadata()), - iacTypes.Int(8080, iacTypes.NewTestMetadata()), + Ports: []compute.PortRange{ + { + Start: iacTypes.IntTest(80), + End: iacTypes.IntTest(80), + }, + { + Start: iacTypes.IntTest(8080), + End: iacTypes.IntTest(8080), + }, + { + Start: iacTypes.IntTest(9090), + End: iacTypes.IntTest(9095), + }, }, }, SourceRanges: []iacTypes.StringValue{ diff --git a/pkg/iac/providers/google/compute/firewall.go b/pkg/iac/providers/google/compute/firewall.go index c122369d9954..19f4044cdb72 100755 --- a/pkg/iac/providers/google/compute/firewall.go +++ b/pkg/iac/providers/google/compute/firewall.go @@ -18,7 +18,13 @@ type FirewallRule struct { Enforced iacTypes.BoolValue IsAllow iacTypes.BoolValue Protocol iacTypes.StringValue - Ports []iacTypes.IntValue + Ports []PortRange +} + +type PortRange struct { + Metadata iacTypes.Metadata + Start iacTypes.IntValue + End iacTypes.IntValue } type IngressRule struct { diff --git a/pkg/iac/rego/schemas/cloud.json b/pkg/iac/rego/schemas/cloud.json index 530ba5bfaa1f..b034f24fa104 100644 --- a/pkg/iac/rego/schemas/cloud.json +++ b/pkg/iac/rego/schemas/cloud.json @@ -1615,10 +1615,18 @@ "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.StringValue" } }, + "fromport": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.IntValue" + }, "protocol": { "type": "object", "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.StringValue" }, + "toport": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.IntValue" + }, "type": { "type": "object", "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.StringValue" @@ -1677,6 +1685,18 @@ "description": { "type": "object", "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.StringValue" + }, + "fromport": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.IntValue" + }, + "protocol": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.StringValue" + }, + "toport": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.IntValue" } } }, @@ -6086,7 +6106,7 @@ "type": "array", "items": { "type": "object", - "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.IntValue" + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.providers.google.compute.PortRange" } }, "protocol": { @@ -6218,6 +6238,23 @@ } } }, + "github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.providers.google.compute.PortRange": { + "type": "object", + "properties": { + "__defsec_metadata": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.Metadata" + }, + "end": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.IntValue" + }, + "start": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.IntValue" + } + } + }, "github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.providers.google.compute.ProjectMetadata": { "type": "object", "properties": { From 37d549e5b86a1c5dce6710fbfd2310aec9abe949 Mon Sep 17 00:00:00 2001 From: bloomadcariad Date: Sun, 22 Sep 2024 23:00:51 -0700 Subject: [PATCH 06/94] fix(misconf): Fixed scope for China Cloud (#7560) --- pkg/fanal/image/registry/azure/azure.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/fanal/image/registry/azure/azure.go b/pkg/fanal/image/registry/azure/azure.go index 67368c8bb3c8..d19392924a10 100644 --- a/pkg/fanal/image/registry/azure/azure.go +++ b/pkg/fanal/image/registry/azure/azure.go @@ -45,7 +45,7 @@ func (r *Registry) CheckOptions(domain string, _ types.RegistryOptions) (intf.Re } else if strings.HasSuffix(domain, chinaAzureURL) { return &RegistryClient{ domain: domain, - scope: scope, + scope: chinaScope, cloud: cloud.AzureChina, }, nil } From 8128ecc9a91e16ca6fc4590a2ded10458addefd0 Mon Sep 17 00:00:00 2001 From: simar7 <1254783+simar7@users.noreply.github.com> Date: Wed, 25 Sep 2024 23:11:33 -0600 Subject: [PATCH 07/94] docs(misconf): Add more info on how to use arbitrary JSON/YAML scan feat (#7458) --- docs/docs/scanner/misconfiguration/index.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/docs/scanner/misconfiguration/index.md b/docs/docs/scanner/misconfiguration/index.md index 9824936b8e53..368b4522b433 100644 --- a/docs/docs/scanner/misconfiguration/index.md +++ b/docs/docs/scanner/misconfiguration/index.md @@ -389,15 +389,27 @@ LOW: Service name "serverless-rest-api-with-pynamodb" is not allowed Ensure that Serverless Framework service names start with "aws-" ``` -You can also pass schemas using the `config-file-schemas` flag. Trivy will use these schemas for file filtering and type checking in Rego checks. If the file does not match any of the passed schemas, it will be ignored. +!!! note + In the case above, the custom check specified has a metadata annotation for the input schema `input: schema["serverless-schema"]`. This allows Trivy to type check the input IaC files provided. + +Optionally, you can also pass schemas using the `config-file-schemas` flag. Trivy will use these schemas for file filtering and type checking in Rego checks. !!! example ```bash $ trivy config --misconfig-scanners=json,yaml --config-check ./serverless.rego --check-namespaces user --config-file-schemas ./serverless-schema.json ./iac ``` +If the `--config-file-schemas` flag is specified Trivy ensures that each input IaC config file being scanned is type-checked against the schema. If the input file does not match any of the passed schemas, it will be ignored. + If the schema is specified in the check metadata and is in the directory specified in the `--config-check` argument, it will be automatically loaded as specified [here](./custom/schema.md#custom-checks-with-custom-schemas), and will only be used for type checking in Rego. +!!! note + If a user specifies the `--config-file-schemas` flag, all input IaC config files are ensured that they pass type-checking. It is not required to pass an input schema in case type checking is not required. This is helpful for scenarios where you simply want to write a Rego check and pass in IaC input for it. Such a use case could include scanning for a new service which Trivy might not support just yet. + +!!! tip + It is also possible to specify multiple input schemas with `--config-file-schema` flag as it can accept a comma seperated list of file paths or a directory as input. In the case of multiple schemas being specified, all of them will be evaluated against all the input files. + + ### Passing custom data You can pass directories including your custom data through `--data` option. This can be repeated for specifying multiple directories. From bbc8e1d8f3e27726ca3d413f7481e7f62814e7b8 Mon Sep 17 00:00:00 2001 From: Sylvain Baubeau Date: Thu, 26 Sep 2024 12:11:53 +0200 Subject: [PATCH 08/94] chore(deps): remove broken replaces for opa and discovery (#7600) --- go.mod | 14 ++++---------- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 483b97ee9acc..af0a26efc67d 100644 --- a/go.mod +++ b/go.mod @@ -88,10 +88,10 @@ require ( github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/mitchellh/mapstructure v1.5.0 github.com/moby/buildkit v0.15.2 - github.com/open-policy-agent/opa v0.67.1 + github.com/open-policy-agent/opa v0.68.1-0.20240903211041-76f7038ea2d1 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0 - github.com/openvex/discovery v0.1.0 + github.com/openvex/discovery v0.1.1-0.20240802171711-7c54efc57553 github.com/openvex/go-vex v0.2.5 github.com/owenrumney/go-sarif/v2 v2.3.3 github.com/owenrumney/squealer v1.2.4 @@ -324,7 +324,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/prometheus/client_golang v1.20.1 // indirect + github.com/prometheus/client_golang v1.20.2 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -389,7 +389,7 @@ require ( google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/grpc v1.65.0 // indirect + google.golang.org/grpc v1.66.0 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect @@ -418,9 +418,3 @@ require ( sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) - -// cf. https://github.com/openvex/discovery/pull/40 -replace github.com/openvex/discovery => github.com/knqyf263/discovery v0.1.1-0.20240726113521-97873005fd03 - -// see https://github.com/open-policy-agent/opa/pull/6970 -replace github.com/open-policy-agent/opa => github.com/nikpivkin/opa v0.0.0-20240829080621-16999fcb5464 diff --git a/go.sum b/go.sum index 6ff7fca55e3b..da3862e7d75d 100644 --- a/go.sum +++ b/go.sum @@ -961,8 +961,6 @@ github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrD github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/knqyf263/discovery v0.1.1-0.20240726113521-97873005fd03 h1:fsWNAqGAbq2sz7q0agtKCq/esMjvReNd26bgWN8Lk6w= -github.com/knqyf263/discovery v0.1.1-0.20240726113521-97873005fd03/go.mod h1:z4b//Qi7p7zcM/c41ogeTy+/nqfMbbeYnfZ+EMCTCD0= github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f h1:GvCU5GXhHq+7LeOzx/haG7HSIZokl3/0GkoUFzsRJjg= github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f/go.mod h1:q59u9px8b7UTj0nIjEjvmTWekazka6xIt6Uogz5Dm+8= github.com/knqyf263/go-deb-version v0.0.0-20230223133812-3ed183d23422 h1:PPPlUUqPP6fLudIK4n0l0VU4KT2cQGnheW9x8pNiCHI= @@ -1118,8 +1116,6 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/nikpivkin/opa v0.0.0-20240829080621-16999fcb5464 h1:jhZ8nLVxOAslgzmPdKTyctfDJkMfRgksCypFriHzf4E= -github.com/nikpivkin/opa v0.0.0-20240829080621-16999fcb5464/go.mod h1:cvSIxY0dexL39hOPqXSZKdBYFNx2Rv8Fu5n3MmTjqtE= github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 h1:Up6+btDp321ZG5/zdSLo48H9Iaq0UQGthrhWC6pCxzE= github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481/go.mod h1:yKZQO8QE2bHlgozqWDiRVqTFlLQSj30K/6SAK8EeYFw= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -1143,6 +1139,8 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= +github.com/open-policy-agent/opa v0.68.1-0.20240903211041-76f7038ea2d1 h1:GQrryTKpunLNDc2NdhNL1FzfrbuNvo45s76anGdqz9k= +github.com/open-policy-agent/opa v0.68.1-0.20240903211041-76f7038ea2d1/go.mod h1:5E5SvaPwTpwt2WM177I9Z3eT7qUpmOGjk1ZdHs+TZ4w= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -1153,6 +1151,8 @@ github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaL github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openvex/discovery v0.1.1-0.20240802171711-7c54efc57553 h1:c4u0GIH0w2Q57Pm2Oldrq6EiHFnLCCnRs98A+ggj/YQ= +github.com/openvex/discovery v0.1.1-0.20240802171711-7c54efc57553/go.mod h1:z4b//Qi7p7zcM/c41ogeTy+/nqfMbbeYnfZ+EMCTCD0= github.com/openvex/go-vex v0.2.5 h1:41utdp2rHgAGCsG+UbjmfMG5CWQxs15nGqir1eRgSrQ= github.com/openvex/go-vex v0.2.5/go.mod h1:j+oadBxSUELkrKh4NfNb+BPo77U3q7gdKME88IO/0Wo= github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U= @@ -1188,8 +1188,8 @@ github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjz github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.20.1 h1:IMJXHOD6eARkQpxo8KkhgEVFlBNm+nkrFUyGlIu7Na8= -github.com/prometheus/client_golang v1.20.1/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg= +github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -2019,8 +2019,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= +google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= From fea7250f7f99a100d67391c0382edd501fa64539 Mon Sep 17 00:00:00 2001 From: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:40:56 +0600 Subject: [PATCH 09/94] ci: cache test images for `integration`, `VM` and `module` tests (#7599) --- .github/workflows/test.yaml | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 13f279b519b7..e26f35890c3d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -82,6 +82,22 @@ jobs: with: aqua_version: v1.25.0 + - name: Generate image list digest + id: image-digest + run: | + IMAGE_LIST=$(skopeo list-tags docker://ghcr.io/aquasecurity/trivy-test-images) + DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) + echo "digest=$DIGEST" >> $GITHUB_OUTPUT + + - name: Restore test images from cache + uses: actions/cache@v4 + id: restore-test-images + with: + path: integration/testdata/fixtures/images + key: cache-test-images-${{ steps.image-digest.outputs.digest }} + restore-keys: + cache-test-images- + - name: Run integration tests run: mage test:integration @@ -122,6 +138,22 @@ jobs: with: aqua_version: v1.25.0 + - name: Generate image list digest + id: image-digest + run: | + IMAGE_LIST=$(skopeo list-tags docker://ghcr.io/aquasecurity/trivy-test-images) + DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) + echo "digest=$DIGEST" >> $GITHUB_OUTPUT + + - name: Restore test images from cache + uses: actions/cache@v4 + id: restore-test-images + with: + path: integration/testdata/fixtures/images + key: cache-test-images-${{ steps.image-digest.outputs.digest }} + restore-keys: + cache-test-images- + - name: Run module integration tests shell: bash run: | @@ -142,6 +174,23 @@ jobs: uses: aquaproj/aqua-installer@v3.0.1 with: aqua_version: v1.25.0 + + - name: Generate image list digest + id: image-digest + run: | + IMAGE_LIST=$(skopeo list-tags docker://ghcr.io/aquasecurity/trivy-test-vm-images) + DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) + echo "digest=$DIGEST" >> $GITHUB_OUTPUT + + - name: Restore test VM images from cache + uses: actions/cache@v4 + id: restore-test-vm-images + with: + path: integration/testdata/fixtures/vm-images + key: cache-test-vm-images-${{ steps.image-digest.outputs.digest }} + restore-keys: + cache-test-vm-images- + - name: Run vm integration tests run: | mage test:vm From 1fdf30a54513e43e343c764f7dafb0721ee6bc83 Mon Sep 17 00:00:00 2001 From: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Date: Thu, 26 Sep 2024 21:42:34 +0600 Subject: [PATCH 10/94] ci: add `workflow_dispatch` trigger for test workflow. (#7606) --- .github/workflows/test.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index e26f35890c3d..dc7d825af1c8 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -8,6 +8,8 @@ on: - 'LICENSE' - '.release-please-manifest.json' ## don't run tests for release-please PRs merge_group: + workflow_dispatch: + env: GO_VERSION: '1.22' jobs: From 3fa24e890e7657c59d3e88dd7a9b74ab07880a74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:22:38 +0000 Subject: [PATCH 11/94] chore(deps): bump the common group across 1 directory with 20 updates (#7604) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: knqyf263 --- go.mod | 94 ++++++++++++------------- go.sum | 212 +++++++++++++++++++++++++++------------------------------ 2 files changed, 147 insertions(+), 159 deletions(-) diff --git a/go.mod b/go.mod index af0a26efc67d..8f5e151e6ef4 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 github.com/BurntSushi/toml v1.4.0 - github.com/CycloneDX/cyclonedx-go v0.9.0 + github.com/CycloneDX/cyclonedx-go v0.9.1 github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible github.com/Masterminds/sprig/v3 v3.3.0 github.com/NYTimes/gziphandler v1.1.1 @@ -29,21 +29,21 @@ require ( github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1 github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240707095038-0300bc49b68b - github.com/aws/aws-sdk-go-v2 v1.30.5 - github.com/aws/aws-sdk-go-v2/config v1.27.33 - github.com/aws/aws-sdk-go-v2/credentials v1.17.32 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.177.2 - github.com/aws/aws-sdk-go-v2/service/ecr v1.32.4 - github.com/aws/aws-sdk-go-v2/service/s3 v1.61.2 - github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 // indirect - github.com/aws/smithy-go v1.20.4 + github.com/aws/aws-sdk-go-v2 v1.31.0 + github.com/aws/aws-sdk-go-v2/config v1.27.38 + github.com/aws/aws-sdk-go-v2/credentials v1.17.36 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.179.1 + github.com/aws/aws-sdk-go-v2/service/ecr v1.35.2 + github.com/aws/aws-sdk-go-v2/service/s3 v1.63.2 + github.com/aws/aws-sdk-go-v2/service/sts v1.31.2 // indirect + github.com/aws/smithy-go v1.21.0 github.com/bitnami/go-version v0.0.0-20231130084017-bb00604d650c github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/cenkalti/backoff/v4 v4.3.0 github.com/cheggaaa/pb/v3 v3.1.5 - github.com/containerd/containerd v1.7.21 + github.com/containerd/containerd v1.7.22 github.com/csaf-poc/csaf_distribution/v3 v3.0.0 - github.com/docker/docker v27.2.0+incompatible + github.com/docker/docker v27.3.1+incompatible github.com/docker/go-connections v0.5.0 github.com/fatih/color v1.17.0 github.com/go-git/go-git/v5 v5.12.0 @@ -62,7 +62,7 @@ require ( github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.7.0 github.com/hashicorp/golang-lru/v2 v2.0.7 - github.com/hashicorp/hc-install v0.8.0 + github.com/hashicorp/hc-install v0.9.0 github.com/hashicorp/hcl/v2 v2.22.0 github.com/hashicorp/terraform-exec v0.21.0 github.com/in-toto/in-toto-golang v0.9.0 @@ -87,7 +87,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/mitchellh/mapstructure v1.5.0 - github.com/moby/buildkit v0.15.2 + github.com/moby/buildkit v0.16.0 github.com/open-policy-agent/opa v0.68.1-0.20240903211041-76f7038ea2d1 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0 @@ -117,21 +117,21 @@ require ( github.com/zclconf/go-cty v1.15.0 github.com/zclconf/go-cty-yaml v1.0.3 go.etcd.io/bbolt v1.3.11 - golang.org/x/crypto v0.26.0 + golang.org/x/crypto v0.27.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect - golang.org/x/mod v0.20.0 - golang.org/x/net v0.28.0 + golang.org/x/mod v0.21.0 + golang.org/x/net v0.29.0 golang.org/x/sync v0.8.0 - golang.org/x/term v0.23.0 - golang.org/x/text v0.17.0 + golang.org/x/term v0.24.0 + golang.org/x/text v0.18.0 golang.org/x/vuln v1.1.3 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 google.golang.org/protobuf v1.34.2 gopkg.in/yaml.v3 v3.0.1 - helm.sh/helm/v3 v3.15.4 - k8s.io/api v0.30.3 + helm.sh/helm/v3 v3.16.1 + k8s.io/api v0.31.0 k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 - modernc.org/sqlite v1.32.0 + modernc.org/sqlite v1.33.1 sigs.k8s.io/yaml v1.4.0 ) @@ -171,18 +171,19 @@ require ( github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go v1.54.6 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.23.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/blang/semver v3.5.1+incompatible // indirect + github.com/blang/semver/v4 v4.0.0 // indirect github.com/briandowns/spinner v1.23.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect @@ -196,18 +197,18 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect github.com/containerd/ttrpc v1.2.5 // indirect - github.com/containerd/typeurl/v2 v2.1.1 // indirect + github.com/containerd/typeurl/v2 v2.2.0 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 // indirect - github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/cyphar/filepath-securejoin v0.3.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/dlclark/regexp2 v1.4.0 // indirect - github.com/docker/cli v27.1.1+incompatible // indirect + github.com/docker/cli v27.2.1+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect @@ -218,7 +219,7 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/evanphx/json-patch v5.7.0+incompatible // indirect + github.com/evanphx/json-patch v5.9.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -274,7 +275,7 @@ require ( github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/jmoiron/sqlx v1.3.5 // indirect + github.com/jmoiron/sqlx v1.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect @@ -299,9 +300,9 @@ require ( github.com/moby/locker v1.0.1 // indirect github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/spdystream v0.4.0 // indirect - github.com/moby/sys/mountinfo v0.7.1 // indirect + github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/moby/sys/sequential v0.5.0 // indirect - github.com/moby/sys/signal v0.7.0 // indirect + github.com/moby/sys/signal v0.7.1 // indirect github.com/moby/sys/user v0.3.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/term v0.5.0 // indirect @@ -331,7 +332,7 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/rubenv/sql-migrate v1.5.2 // indirect + github.com/rubenv/sql-migrate v1.7.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -371,7 +372,7 @@ require ( github.com/yusufpapurcu/wmi v1.2.4 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect @@ -381,7 +382,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sys v0.23.0 // indirect + golang.org/x/sys v0.25.0 // indirect golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 // indirect golang.org/x/time v0.6.0 // indirect golang.org/x/tools v0.24.0 // indirect @@ -391,20 +392,21 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/grpc v1.66.0 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/apiextensions-apiserver v0.30.3 // indirect + k8s.io/apiextensions-apiserver v0.31.0 // indirect k8s.io/apimachinery v0.31.0 // indirect - k8s.io/apiserver v0.30.3 // indirect - k8s.io/cli-runtime v0.30.3 // indirect - k8s.io/client-go v0.30.3 // indirect - k8s.io/component-base v0.30.3 // indirect + k8s.io/apiserver v0.31.0 // indirect + k8s.io/cli-runtime v0.31.0 // indirect + k8s.io/client-go v0.31.0 // indirect + k8s.io/component-base v0.31.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/kubectl v0.30.3 // indirect + k8s.io/kubectl v0.31.0 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect modernc.org/libc v1.55.3 // indirect modernc.org/mathutil v1.6.0 // indirect @@ -414,7 +416,7 @@ require ( mvdan.cc/sh/v3 v3.8.0 // indirect oras.land/oras-go v1.2.5 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect - sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/kustomize/api v0.17.2 // indirect + sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) diff --git a/go.sum b/go.sum index da3862e7d75d..b284e23f5722 100644 --- a/go.sum +++ b/go.sum @@ -241,8 +241,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CycloneDX/cyclonedx-go v0.9.0 h1:inaif7qD8bivyxp7XLgxUYtOXWtDez7+j72qKTMQTb8= -github.com/CycloneDX/cyclonedx-go v0.9.0/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw= +github.com/CycloneDX/cyclonedx-go v0.9.1 h1:yffaWOZsv77oTJa/SdVZYdgAgFioCeycBUKkqS2qzQM= +github.com/CycloneDX/cyclonedx-go v0.9.1/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible h1:juIaKLLVhqzP55d8x4cSVgwyQv76Z55/fRv/UBr2KkQ= @@ -364,44 +364,44 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:W github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.54.6 h1:HEYUib3yTt8E6vxjMWM3yAq5b+qjj/6aKA62mkgux9g= github.com/aws/aws-sdk-go v1.54.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/aws/aws-sdk-go-v2 v1.30.5 h1:mWSRTwQAb0aLE17dSzztCVJWI9+cRMgqebndjwDyK0g= -github.com/aws/aws-sdk-go-v2 v1.30.5/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= -github.com/aws/aws-sdk-go-v2/config v1.27.33 h1:Nof9o/MsmH4oa0s2q9a0k7tMz5x/Yj5k06lDODWz3BU= -github.com/aws/aws-sdk-go-v2/config v1.27.33/go.mod h1:kEqdYzRb8dd8Sy2pOdEbExTTF5v7ozEXX0McgPE7xks= -github.com/aws/aws-sdk-go-v2/credentials v1.17.32 h1:7Cxhp/BnT2RcGy4VisJ9miUPecY+lyE9I8JvcZofn9I= -github.com/aws/aws-sdk-go-v2/credentials v1.17.32/go.mod h1:P5/QMF3/DCHbXGEGkdbilXHsyTBX5D3HSwcrSc9p20I= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 h1:pfQ2sqNpMVK6xz2RbqLEL0GH87JOwSxPV2rzm8Zsb74= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13/go.mod h1:NG7RXPUlqfsCLLFfi0+IpKN4sCB9D9fw/qTaSB+xRoU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 h1:pI7Bzt0BJtYA0N/JEC6B8fJ4RBrEMi1LBrkMdFYNSnQ= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17/go.mod h1:Dh5zzJYMtxfIjYW+/evjQ8uj2OyR/ve2KROHGHlSFqE= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 h1:Mqr/V5gvrhA2gvgnF42Zh5iMiQNcOYthFYwCyrnuWlc= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17/go.mod h1:aLJpZlCmjE+V+KtN1q1uyZkfnUWpQGpbsn89XPKyzfU= +github.com/aws/aws-sdk-go-v2 v1.31.0 h1:3V05LbxTSItI5kUqNwhJrrrY1BAXxXt0sN0l72QmG5U= +github.com/aws/aws-sdk-go-v2 v1.31.0/go.mod h1:ztolYtaEUtdpf9Wftr31CJfLVjOnD/CVRkKOOYgF8hA= +github.com/aws/aws-sdk-go-v2/config v1.27.38 h1:mMVyJJuSUdbD4zKXoxDgWrgM60QwlFEg+JhihCq6wCw= +github.com/aws/aws-sdk-go-v2/config v1.27.38/go.mod h1:6xOiNEn58bj/64MPKx89r6G/el9JZn8pvVbquSqTKK4= +github.com/aws/aws-sdk-go-v2/credentials v1.17.36 h1:zwI5WrT+oWWfzSKoTNmSyeBKQhsFRJRv+PGW/UZW+Yk= +github.com/aws/aws-sdk-go-v2/credentials v1.17.36/go.mod h1:3AG/sY1rc9NJrNWcN/3KPU4SIDPGTrd/qegKB0TnFdE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 h1:C/d03NAmh8C4BZXhuRNboF/DqhBkBCeDiJDcaqIT5pA= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14/go.mod h1:7I0Ju7p9mCIdlrfS+JCgqcYD0VXz/N4yozsox+0o078= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 h1:kYQ3H1u0ANr9KEKlGs/jTLrBFPo8P8NaH/w7A01NeeM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18/go.mod h1:r506HmK5JDUh9+Mw4CfGJGSSoqIiLCndAuqXuhbv67Y= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 h1:Z7IdFUONvTcvS7YuhtVxN99v2cCoHRXOS4mTr0B/pUc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18/go.mod h1:DkKMmksZVVyat+Y+r1dEOgJEfUeA7UngIHWeKsi0yNc= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1 h1:SeDJWG4pmye+/aO6k+zt9clPTUy1MXqUmkW8rbAddQg= github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1/go.mod h1:wRzaW0v9GGQS0h//wpsVDw3Hah5gs5UP+NxoyGeZIGM= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.177.2 h1:QUUvxEs9q1DsYCaWaRrV8i7n82Adm34jrHb6OPjXPqc= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.177.2/go.mod h1:TFSALWR7Xs7+KyMM87ZAYxncKFBvzEt2rpK/BJCH2ps= -github.com/aws/aws-sdk-go-v2/service/ecr v1.32.4 h1:nQAU2Yr+afkAvIV39mg7LrNYFNQP7ShwbmiJqx2fUKA= -github.com/aws/aws-sdk-go-v2/service/ecr v1.32.4/go.mod h1:keOS9j4fv5ASh7dV29lIpGw2QgoJwGFAyMU0uPvfax4= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.179.1 h1:TwFjSwRn1kR1i1qeq5cQBRwRaZ80JQS8BHsJTb6QBk8= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.179.1/go.mod h1:W6sNzs5T4VpZn1Vy+FMKw8s24vt5k6zPJXcNOK0asBo= +github.com/aws/aws-sdk-go-v2/service/ecr v1.35.2 h1:bVNvja4oEB7v+VL1yP46hWthCPp+KYpZBLS2AifM5PY= +github.com/aws/aws-sdk-go-v2/service/ecr v1.35.2/go.mod h1:oRaGEExKI6Pqcow+Tt7wpJf73/Srcj/CUJv5Eb9QFhg= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.18.2 h1:PpbXaecV3sLAS6rjQiaKw4/jyq3Z8gNzmoJupHAoBp0= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.18.2/go.mod h1:fUHpGXr4DrXkEDpGAjClPsviWf+Bszeb0daKE0blxv8= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 h1:rfprUlsdzgl7ZL2KlXiUAoJnI/VxfHCvDFr2QDFj6u4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19/go.mod h1:SCWkEdRq8/7EK60NcvvQ6NXKuTcchAD4ROAsC37VEZE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 h1:QFASJGfT8wMXtuP3D5CRmMjARHv9ZmzFUMJznHDOY3w= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5/go.mod h1:QdZ3OmoIjSX+8D1OPAzPxDfjXASbBMDsz9qvtyIhtik= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 h1:Xbwbmk44URTiHNx6PNo0ujDE6ERlsCKJD3u1zfnzAPg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20/go.mod h1:oAfOFzUB14ltPZj1rWwRc3d/6OgD76R8KlvU3EqM9Fg= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.61.2 h1:Kp6PWAlXwP1UvIflkIP6MFZYBNDCa4mFCGtxrpICVOg= -github.com/aws/aws-sdk-go-v2/service/s3 v1.61.2/go.mod h1:5FmD/Dqq57gP+XwaUnd5WFPipAuzrf0HmupX27Gvjvc= -github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 h1:pIaGg+08llrP7Q5aiz9ICWbY8cqhTkyy+0SHvfzQpTc= -github.com/aws/aws-sdk-go-v2/service/sso v1.22.7/go.mod h1:eEygMHnTKH/3kNp9Jr1n3PdejuSNcgwLe1dWgQtO0VQ= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 h1:/Cfdu0XV3mONYKaOt1Gr0k1KvQzkzPyiKUdlWJqy+J4= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7/go.mod h1:bCbAxKDqNvkHxRaIMnyVPXPo+OaPRwvmgzMxbz1VKSA= -github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 h1:NKTa1eqZYw8tiHSRGpP0VtTdub/8KNk8sDkNPFaOKDE= -github.com/aws/aws-sdk-go-v2/service/sts v1.30.7/go.mod h1:NXi1dIAGteSaRLqYgarlhP/Ij0cFT+qmCwiJqWh/U5o= -github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= -github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aws/aws-sdk-go-v2/service/s3 v1.63.2 h1:1iXmXy8SJzQVMGvo40TSzBYS9ig6BSyXfRIMzLfmBfE= +github.com/aws/aws-sdk-go-v2/service/s3 v1.63.2/go.mod h1:NLTqRLe3pUNu3nTEHI6XlHLKYmc8fbHUdMxAB6+s41Q= +github.com/aws/aws-sdk-go-v2/service/sso v1.23.2 h1:yzi/y/vKlLyzOfG7pSu5ONNGRxHIgLeDrV4w2AMRCo0= +github.com/aws/aws-sdk-go-v2/service/sso v1.23.2/go.mod h1:XRlMvmad0ZNL+75C5FYdMvbbLkd6qiqz6foR1nA1PXY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.2 h1:3gb6pYhYLjo8rB1h2Tqs61wpjRd3rQymYcVq/pp0yxI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.2/go.mod h1:FnvDM4sfa+isJ3kDXIzAB9GAwVSzFzSy97uZ3IsHo4E= +github.com/aws/aws-sdk-go-v2/service/sts v1.31.2 h1:O6tyji8mXmBGsHvTCB0VIhrDw19lGTUSbKIyjnw79s8= +github.com/aws/aws-sdk-go-v2/service/sts v1.31.2/go.mod h1:yMWe0F+XG0DkRZK5ODZhG7BEFYhLXi2dqGsv6tX0cgI= +github.com/aws/smithy-go v1.21.0 h1:H7L8dtDRk0P1Qm6y0ji7MCYMQObJ5R9CRpyPhRUkLYA= +github.com/aws/smithy-go v1.21.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8 h1:SoFYaT9UyGkR0+nogNyD/Lj+bsixB+SNuAS4ABlEs6M= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8/go.mod h1:2JF49jcDOrLStIXN/j/K1EKRq8a8R2qRnlZA6/o/c7c= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -414,6 +414,8 @@ github.com/bitnami/go-version v0.0.0-20231130084017-bb00604d650c h1:C4UZIaS+HAw+ github.com/bitnami/go-version v0.0.0-20231130084017-bb00604d650c/go.mod h1:9iglf1GG4oNRJ39bZ5AZrjgAFD2RwQbXw6Qf7Cs47wo= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= @@ -478,8 +480,8 @@ github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= -github.com/containerd/containerd v1.7.21 h1:USGXRK1eOC/SX0L195YgxTHb0a00anxajOzgfN0qrCA= -github.com/containerd/containerd v1.7.21/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= +github.com/containerd/containerd v1.7.22 h1:nZuNnNRA6T6jB975rx2RRNqqH2k6ELYKDZfqTHqwyy0= +github.com/containerd/containerd v1.7.22/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA= github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= @@ -496,8 +498,8 @@ github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk= github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU= github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= -github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4= -github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= +github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= +github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU= github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac= @@ -512,8 +514,8 @@ github.com/csaf-poc/csaf_distribution/v3 v3.0.0 h1:ob9+Fmpff0YWgTP3dYaw7G2hKQ9ce github.com/csaf-poc/csaf_distribution/v3 v3.0.0/go.mod h1:uilCTiNKivq+6zrDvjtZaUeLk70oe21iwKivo6ILwlQ= github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 h1:2Dx4IHfC1yHWI12AxQDJM1QbRCDfk6M+blLzlZCXdrc= github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= -github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= -github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.3.1 h1:1V7cHiaW+C+39wEfpH6XlLBQo3j/PciWFrgfCLS8XrE= +github.com/cyphar/filepath-securejoin v0.3.1/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -541,12 +543,12 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= -github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.2.1+incompatible h1:U5BPtiD0viUzjGAjV1p0MGB8eVA3L3cbIrnyWmSJI70= +github.com/docker/cli v27.2.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4= -github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -582,8 +584,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= -github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= +github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -681,22 +683,15 @@ github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtP github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= -github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= -github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= -github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= -github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= -github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-yaml v1.8.1/go.mod h1:wS4gNoLalDSJxo/SpngzPQ2BN4uuZVLCmbM4S3vd4+Y= @@ -902,8 +897,8 @@ github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/hashicorp/hc-install v0.8.0 h1:LdpZeXkZYMQhoKPCecJHlKvUkQFixN/nvyR1CdfOLjI= -github.com/hashicorp/hc-install v0.8.0/go.mod h1:+MwJYjDfCruSD/udvBmRB22Nlkwwkwf5sAB6uTIhSaU= +github.com/hashicorp/hc-install v0.9.0 h1:2dIk8LcvANwtv3QZLckxcjyF5w8KVtiMxu6G6eLhghE= +github.com/hashicorp/hc-install v0.9.0/go.mod h1:+6vOP+mf3tuGgMApVYtmsnDoKWMDcFXeTxCACYZ8SFg= github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/hcl/v2 v2.22.0 h1:hkZ3nCtqeJsDhPRFz5EA9iwcG1hNWGePOTw6oyul12M= @@ -939,8 +934,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmhodges/clock v1.2.0 h1:eq4kys+NI0PLngzaHEe7AmPT90XMGIEySD1JfV1PDIs= github.com/jmhodges/clock v1.2.0/go.mod h1:qKjhA7x7u/lQpPB1XAqX1b1lCI/w3/fNuYpI/ZjLynI= -github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= -github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -950,8 +945,6 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= -github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -997,7 +990,6 @@ github.com/liamg/jfather v0.0.7 h1:Xf78zS263yfT+xr2VSo6+kyAy4ROlCacRqJG7s5jt4k= github.com/liamg/jfather v0.0.7/go.mod h1:xXBGiBoiZ6tmHhfy5Jzw8sugzajwYdi6VosIpB3/cPM= github.com/liamg/memoryfs v1.6.0 h1:jAFec2HI1PgMTem5gR7UT8zi9u4BfG5jorCRlLH06W8= github.com/liamg/memoryfs v1.6.0/go.mod h1:z7mfqXFQS8eSeBBsFjYLlxYRMRyiPktytvYCYTb3BSk= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= @@ -1013,12 +1005,6 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= -github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= -github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= -github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= -github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/masahiro331/go-disk v0.0.0-20240625071113-56c933208fee h1:cgm8mE25x5XXX2oyvJDlyJ72K+rDu/4ZCYce2worNb8= github.com/masahiro331/go-disk v0.0.0-20240625071113-56c933208fee/go.mod h1:rojbW5tVhH1cuVYFKZS+QX+VGXK45JVsRO+jW92kkKM= github.com/masahiro331/go-ebs-file v0.0.0-20240917043618-e6d2bea5c32e h1:nCgF1JEYIS8KNuJtIeUrmjjhktIMKWNmASZqwK2ynu0= @@ -1050,7 +1036,6 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -1074,8 +1059,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/buildkit v0.15.2 h1:DnONr0AoceTWyv+plsQ7IhkSaj+6o0WyoaxYPyTFIxs= -github.com/moby/buildkit v0.15.2/go.mod h1:Yis8ZMUJTHX9XhH9zVyK2igqSHV3sxi3UN0uztZocZk= +github.com/moby/buildkit v0.16.0 h1:wOVBj1o5YNVad/txPQNXUXdelm7Hs/i0PUFjzbK0VKE= +github.com/moby/buildkit v0.16.0/go.mod h1:Xqx/5GlrqE1yIRORk0NSCVDFpQAU1WjlT6KHYZdisIQ= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= @@ -1084,12 +1069,12 @@ github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkV github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= -github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= -github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= +github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= -github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= +github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0= +github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8= github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= @@ -1137,8 +1122,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= -github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/open-policy-agent/opa v0.68.1-0.20240903211041-76f7038ea2d1 h1:GQrryTKpunLNDc2NdhNL1FzfrbuNvo45s76anGdqz9k= github.com/open-policy-agent/opa v0.68.1-0.20240903211041-76f7038ea2d1/go.mod h1:5E5SvaPwTpwt2WM177I9Z3eT7qUpmOGjk1ZdHs+TZ4w= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -1219,8 +1204,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rubenv/sql-migrate v1.5.2 h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzFtS0= -github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWxs+kmzlg0Is= +github.com/rubenv/sql-migrate v1.7.0 h1:HtQq1xyTN2ISmQDggnh0c9U3JlP8apWh8YO2jzlXpTI= +github.com/rubenv/sql-migrate v1.7.0/go.mod h1:S4wtDEG1CKn+0ShpTtzWhFpHHI5PvCUtiGI+C+Z2THE= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1428,8 +1413,8 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= @@ -1472,8 +1457,8 @@ golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1515,8 +1500,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1575,8 +1560,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1686,7 +1671,6 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1713,8 +1697,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 h1:FemxDzfMUcK2f3YY4H+05K9CDzbSVr2+q/JKN45pey0= golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1725,8 +1709,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1741,8 +1725,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2049,6 +2033,8 @@ gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= @@ -2075,8 +2061,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -helm.sh/helm/v3 v3.15.4 h1:UFHd6oZ1IN3FsUZ7XNhOQDyQ2QYknBNWRHH57e9cbHY= -helm.sh/helm/v3 v3.15.4/go.mod h1:phOwlxqGSgppCY/ysWBNRhG3MtnpsttOzxaTK+Mt40E= +helm.sh/helm/v3 v3.16.1 h1:cER6tI/8PgUAsaJaQCVBUg3VI9KN4oVaZJgY60RIc0c= +helm.sh/helm/v3 v3.16.1/go.mod h1:r+xBHHP20qJeEqtvBXMf7W35QDJnzY/eiEBzt+TfHps= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2084,26 +2070,26 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.30.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ= -k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04= -k8s.io/apiextensions-apiserver v0.30.3 h1:oChu5li2vsZHx2IvnGP3ah8Nj3KyqG3kRSaKmijhB9U= -k8s.io/apiextensions-apiserver v0.30.3/go.mod h1:uhXxYDkMAvl6CJw4lrDN4CPbONkF3+XL9cacCT44kV4= +k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo= +k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE= +k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= +k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/apiserver v0.30.3 h1:QZJndA9k2MjFqpnyYv/PH+9PE0SHhx3hBho4X0vE65g= -k8s.io/apiserver v0.30.3/go.mod h1:6Oa88y1CZqnzetd2JdepO0UXzQX4ZnOekx2/PtEjrOg= -k8s.io/cli-runtime v0.30.3 h1:aG69oRzJuP2Q4o8dm+f5WJIX4ZBEwrvdID0+MXyUY6k= -k8s.io/cli-runtime v0.30.3/go.mod h1:hwrrRdd9P84CXSKzhHxrOivAR9BRnkMt0OeP5mj7X30= -k8s.io/client-go v0.30.3 h1:bHrJu3xQZNXIi8/MoxYtZBBWQQXwy16zqJwloXXfD3k= -k8s.io/client-go v0.30.3/go.mod h1:8d4pf8vYu665/kUbsxWAQ/JDBNWqfFeZnvFiVdmx89U= -k8s.io/component-base v0.30.3 h1:Ci0UqKWf4oiwy8hr1+E3dsnliKnkMLZMVbWzeorlk7s= -k8s.io/component-base v0.30.3/go.mod h1:C1SshT3rGPCuNtBs14RmVD2xW0EhRSeLvBh7AGk1quA= +k8s.io/apiserver v0.31.0 h1:p+2dgJjy+bk+B1Csz+mc2wl5gHwvNkC9QJV+w55LVrY= +k8s.io/apiserver v0.31.0/go.mod h1:KI9ox5Yu902iBnnyMmy7ajonhKnkeZYJhTZ/YI+WEMk= +k8s.io/cli-runtime v0.31.0 h1:V2Q1gj1u3/WfhD475HBQrIYsoryg/LrhhK4RwpN+DhA= +k8s.io/cli-runtime v0.31.0/go.mod h1:vg3H94wsubuvWfSmStDbekvbla5vFGC+zLWqcf+bGDw= +k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8= +k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU= +k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs= +k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/kubectl v0.30.3 h1:YIBBvMdTW0xcDpmrOBzcpUVsn+zOgjMYIu7kAq+yqiI= -k8s.io/kubectl v0.30.3/go.mod h1:IcR0I9RN2+zzTRUa1BzZCm4oM0NLOawE6RzlDvd1Fpo= +k8s.io/kubectl v0.31.0 h1:kANwAAPVY02r4U4jARP/C+Q1sssCcN/1p9Nk+7BQKVg= +k8s.io/kubectl v0.31.0/go.mod h1:pB47hhFypGsaHAPjlwrNbvhXgmuAr01ZBvAIIUaI8d4= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= @@ -2126,8 +2112,8 @@ modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s= -modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= +modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM= +modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= @@ -2141,10 +2127,10 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= +sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g= +sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0= +sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ= +sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= sigs.k8s.io/release-utils v0.7.7 h1:JKDOvhCk6zW8ipEOkpTGDH/mW3TI+XqtPp16aaQ79FU= sigs.k8s.io/release-utils v0.7.7/go.mod h1:iU7DGVNi3umZJ8q6aHyUFzsDUIaYwNnNKGHo3YE5E3s= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= From 13ef3e7d62ba2bcb3a04d7b44f79b1299674b480 Mon Sep 17 00:00:00 2001 From: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Date: Thu, 26 Sep 2024 23:26:50 +0600 Subject: [PATCH 12/94] fix(db): check `DownloadedAt` for `trivy-java-db` (#7592) --- pkg/javadb/client.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/pkg/javadb/client.go b/pkg/javadb/client.go index ca055a0c333f..936c2d40c028 100644 --- a/pkg/javadb/client.go +++ b/pkg/javadb/client.go @@ -53,7 +53,7 @@ func (u *Updater) Update() error { } } - if (meta.Version != SchemaVersion || meta.NextUpdate.Before(time.Now().UTC())) && !u.skip { + if (meta.Version != SchemaVersion || !u.isNewDB(meta)) && !u.skip { // Download DB log.Info("Java DB Repository", log.Any("repository", u.repo)) log.Info("Downloading the Java DB...") @@ -85,6 +85,20 @@ func (u *Updater) Update() error { return nil } +func (u *Updater) isNewDB(meta db.Metadata) bool { + now := time.Now().UTC() + if now.Before(meta.NextUpdate) { + log.Debug("Java DB update was skipped because the local Java DB is the latest") + return true + } + + if now.Before(meta.DownloadedAt.Add(time.Hour * 24)) { // 1 day + log.Debug("Java DB update was skipped because the local Java DB was downloaded during the last day") + return true + } + return false +} + func Init(cacheDir string, javaDBRepository name.Reference, skip, quiet bool, registryOption ftypes.RegistryOptions) { updater = &Updater{ repo: javaDBRepository, From a8fbe46119adbd89f827a75c75b9e97d392f1842 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Fri, 27 Sep 2024 08:03:46 +0600 Subject: [PATCH 13/94] fix: allow access to '..' in mapfs (#7575) Signed-off-by: nikpivkin --- pkg/mapfs/fs.go | 12 ++++++++---- pkg/mapfs/fs_test.go | 23 +++++++++++++++++++++++ pkg/mapfs/testdata/subdir/..foo.txt | 0 pkg/mapfs/testdata/subdir/foo.txt | 0 4 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 pkg/mapfs/testdata/subdir/..foo.txt create mode 100644 pkg/mapfs/testdata/subdir/foo.txt diff --git a/pkg/mapfs/fs.go b/pkg/mapfs/fs.go index 4cba59263c37..5ce894b8101c 100644 --- a/pkg/mapfs/fs.go +++ b/pkg/mapfs/fs.go @@ -123,7 +123,7 @@ func (m *FS) CopyFilesUnder(dir string) error { // Stat returns a FileInfo describing the file. func (m *FS) Stat(name string) (fs.FileInfo, error) { - if strings.HasPrefix(name, "../") && m.underlyingRoot != "" { + if m.isPathAboveRoot(name) { return os.Stat(filepath.Join(m.underlyingRoot, name)) } @@ -145,7 +145,7 @@ func (m *FS) Stat(name string) (fs.FileInfo, error) { // ReadDir reads the named directory // and returns a list of directory entries sorted by filename. func (m *FS) ReadDir(name string) ([]fs.DirEntry, error) { - if strings.HasPrefix(name, "../") && m.underlyingRoot != "" { + if m.isPathAboveRoot(name) { return os.ReadDir(filepath.Join(m.underlyingRoot, name)) } return m.root.ReadDir(cleanPath(name)) @@ -153,7 +153,7 @@ func (m *FS) ReadDir(name string) ([]fs.DirEntry, error) { // Open opens the named file for reading. func (m *FS) Open(name string) (fs.File, error) { - if strings.HasPrefix(name, "../") && m.underlyingRoot != "" { + if m.isPathAboveRoot(name) { return os.Open(filepath.Join(m.underlyingRoot, name)) } return m.root.Open(cleanPath(name)) @@ -188,7 +188,7 @@ func (m *FS) MkdirAll(path string, perm fs.FileMode) error { // The caller is permitted to modify the returned byte slice. // This method should return a copy of the underlying data. func (m *FS) ReadFile(name string) ([]byte, error) { - if strings.HasPrefix(name, "../") && m.underlyingRoot != "" { + if m.isPathAboveRoot(name) { return os.ReadFile(filepath.Join(m.underlyingRoot, name)) } @@ -245,3 +245,7 @@ func cleanPath(path string) string { path = strings.TrimLeft(path, "/") // Remove the leading slash return path } + +func (m *FS) isPathAboveRoot(name string) bool { + return (name == ".." || strings.HasPrefix(name, "../")) && m.underlyingRoot != "" +} diff --git a/pkg/mapfs/fs_test.go b/pkg/mapfs/fs_test.go index 22b659d7f387..d00d5626a9a9 100644 --- a/pkg/mapfs/fs_test.go +++ b/pkg/mapfs/fs_test.go @@ -478,3 +478,26 @@ func TestFS_RemoveAll(t *testing.T) { require.ErrorIs(t, err, fs.ErrNotExist) }) } + +func TestFS_WithUnderlyingRoot(t *testing.T) { + root := "testdata/subdir" + fsys := mapfs.New(mapfs.WithUnderlyingRoot(root)) + require.NoError(t, fsys.WriteFile("foo.txt", root+"/foo.txt")) + require.NoError(t, fsys.WriteFile("..foo.txt", root+"/..foo.txt")) + + fi, err := fsys.Stat("..") + require.NoError(t, err) + assert.True(t, fi.IsDir()) + + fi, err = fsys.Stat("../hello.txt") + require.NoError(t, err) + assert.False(t, fi.IsDir()) + + fi, err = fsys.Stat("foo.txt") + require.NoError(t, err) + assert.False(t, fi.IsDir()) + + fi, err = fsys.Stat("..foo.txt") + require.NoError(t, err) + assert.False(t, fi.IsDir()) +} diff --git a/pkg/mapfs/testdata/subdir/..foo.txt b/pkg/mapfs/testdata/subdir/..foo.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/pkg/mapfs/testdata/subdir/foo.txt b/pkg/mapfs/testdata/subdir/foo.txt new file mode 100644 index 000000000000..e69de29bb2d1 From 9baf6589354cee490686ae636570dcaecf17ad6c Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Fri, 27 Sep 2024 14:32:46 +0400 Subject: [PATCH 14/94] test: use a local registry for remote scanning (#7607) Signed-off-by: knqyf263 --- integration/registry_test.go | 64 ++- .../testdata/alpine-310-registry.json.golden | 374 ------------------ pkg/fanal/test/integration/library_test.go | 48 --- 3 files changed, 47 insertions(+), 439 deletions(-) delete mode 100644 integration/testdata/alpine-310-registry.json.golden diff --git a/integration/registry_test.go b/integration/registry_test.go index 9a2570062e56..3831ea9a280e 100644 --- a/integration/registry_test.go +++ b/integration/registry_test.go @@ -10,7 +10,6 @@ import ( "crypto/x509" "encoding/json" "fmt" - "github.com/aquasecurity/trivy/pkg/types" "io" "net/http" "net/url" @@ -18,6 +17,8 @@ import ( "path/filepath" "testing" + "github.com/aquasecurity/trivy/pkg/types" + dockercontainer "github.com/docker/docker/api/types/container" "github.com/docker/go-connections/nat" "github.com/google/go-containerregistry/pkg/authn" @@ -152,32 +153,59 @@ func TestRegistry(t *testing.T) { name string imageName string imageFile string + os string option registryOption golden string wantErr string }{ { - name: "happy path with username/password", + name: "authenticate with username/password", imageName: "alpine:3.10", imageFile: "testdata/fixtures/images/alpine-310.tar.gz", + os: "alpine 3.10.2", option: registryOption{ AuthURL: authURL, Username: authUsername, Password: authPassword, }, - golden: "testdata/alpine-310-registry.json.golden", + golden: "testdata/alpine-310.json.golden", }, { - name: "happy path with registry token", + name: "authenticate with registry token", imageName: "alpine:3.10", imageFile: "testdata/fixtures/images/alpine-310.tar.gz", + os: "alpine 3.10.2", option: registryOption{ AuthURL: authURL, Username: authUsername, Password: authPassword, RegistryToken: true, }, - golden: "testdata/alpine-310-registry.json.golden", + golden: "testdata/alpine-310.json.golden", + }, + { + name: "amazonlinux 2", + imageName: "amazonlinux:2", + imageFile: "testdata/fixtures/images/amazon-2.tar.gz", + os: "amazon 2 (Karoo)", + option: registryOption{ + AuthURL: authURL, + Username: authUsername, + Password: authPassword, + }, + golden: "testdata/amazon-2.json.golden", + }, + { + name: "debian buster", + imageName: "debian:buster", + imageFile: "testdata/fixtures/images/debian-buster.tar.gz", + os: "debian 10.1", + option: registryOption{ + AuthURL: authURL, + Username: authUsername, + Password: authPassword, + }, + golden: "testdata/debian-buster.json.golden", }, { name: "sad path", @@ -187,25 +215,25 @@ func TestRegistry(t *testing.T) { }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - s := fmt.Sprintf("%s/%s", registryURL.Host, tc.imageName) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := fmt.Sprintf("%s/%s", registryURL.Host, tt.imageName) imageRef, err := name.ParseReference(s) require.NoError(t, err) // Load a test image from the tar file, tag it and push to the test registry. - err = replicateImage(imageRef, tc.imageFile, auth) + err = replicateImage(imageRef, tt.imageFile, auth) require.NoError(t, err) - osArgs, err := scan(t, imageRef, baseDir, tc.golden, tc.option) + osArgs, err := scan(t, imageRef, baseDir, tt.option) // Run Trivy - runTest(t, osArgs, tc.golden, "", types.FormatJSON, runOptions{ - wantErr: tc.wantErr, - override: overrideFuncs(overrideUID, func(t *testing.T, _, got *types.Report) { - got.ArtifactName = tc.imageName - for i := range got.Results { - got.Results[i].Target = fmt.Sprintf("%s (alpine 3.10.2)", tc.imageName) + runTest(t, osArgs, tt.golden, "", types.FormatJSON, runOptions{ + wantErr: tt.wantErr, + override: overrideFuncs(overrideUID, func(t *testing.T, want, got *types.Report) { + want.ArtifactName = s + for i := range want.Results { + want.Results[i].Target = fmt.Sprintf("%s (%s)", s, tt.os) } }), }) @@ -213,7 +241,7 @@ func TestRegistry(t *testing.T) { } } -func scan(t *testing.T, imageRef name.Reference, baseDir, goldenFile string, opt registryOption) ([]string, error) { +func scan(t *testing.T, imageRef name.Reference, baseDir string, opt registryOption) ([]string, error) { // Set up testing DB cacheDir := initDB(t) @@ -232,6 +260,8 @@ func scan(t *testing.T, imageRef name.Reference, baseDir, goldenFile string, opt "image", "--format", "json", + "--image-src", + "remote", "--skip-update", imageRef.Name(), } diff --git a/integration/testdata/alpine-310-registry.json.golden b/integration/testdata/alpine-310-registry.json.golden deleted file mode 100644 index 51100d633f53..000000000000 --- a/integration/testdata/alpine-310-registry.json.golden +++ /dev/null @@ -1,374 +0,0 @@ -{ - "SchemaVersion": 2, - "CreatedAt": "2021-08-25T12:20:30.000000005Z", - "ArtifactName": "alpine:3.10", - "ArtifactType": "container_image", - "Metadata": { - "OS": { - "Family": "alpine", - "Name": "3.10.2", - "EOSL": true - }, - "ImageID": "sha256:961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4", - "DiffIDs": [ - "sha256:03901b4a2ea88eeaad62dbe59b072b28b6efa00491962b8741081c5df50c65e0" - ], - "RepoTags": [ - "alpine:3.10" - ], - "RepoDigests": [ - "alpine@sha256:b1c5a500182b21d0bfa5a584a8526b56d8be316f89e87d951be04abed2446e60" - ], - "ImageConfig": { - "architecture": "amd64", - "container": "0a80155a31551fcc1a36fccbbda79fcd3f0b1c7d270653d00310e6e2217c57e6", - "created": "2019-08-20T20:19:55.211423266Z", - "docker_version": "18.06.1-ce", - "history": [ - { - "created": "2019-08-20T20:19:55.062606894Z", - "created_by": "/bin/sh -c #(nop) ADD file:fe64057fbb83dccb960efabbf1cd8777920ef279a7fa8dbca0a8801c651bdf7c in / " - }, - { - "created": "2019-08-20T20:19:55.211423266Z", - "created_by": "/bin/sh -c #(nop) CMD [\"/bin/sh\"]", - "empty_layer": true - } - ], - "os": "linux", - "rootfs": { - "type": "layers", - "diff_ids": [ - "sha256:03901b4a2ea88eeaad62dbe59b072b28b6efa00491962b8741081c5df50c65e0" - ] - }, - "config": { - "Cmd": [ - "/bin/sh" - ], - "Env": [ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - ], - "Image": "sha256:06f4121dff4d0123ce11bd2e44f48da9ba9ddcd23ae376ea1f363f63ea0849b5", - "ArgsEscaped": true - } - } - }, - "Results": [ - { - "Target": "alpine:3.10 (alpine 3.10.2)", - "Class": "os-pkgs", - "Type": "alpine", - "Vulnerabilities": [ - { - "VulnerabilityID": "CVE-2019-1549", - "PkgID": "libcrypto1.1@1.1.1c-r0", - "PkgName": "libcrypto1.1", - "PkgIdentifier": { - "PURL": "pkg:apk/alpine/libcrypto1.1@1.1.1c-r0?arch=x86_64\u0026distro=3.10.2" - }, - "InstalledVersion": "1.1.1c-r0", - "FixedVersion": "1.1.1d-r0", - "Status": "fixed", - "Layer": { - "Digest": "sha256:9d48c3bd43c520dc2784e868a780e976b207cbf493eaff8c6596eb871cbd9609", - "DiffID": "sha256:03901b4a2ea88eeaad62dbe59b072b28b6efa00491962b8741081c5df50c65e0" - }, - "SeveritySource": "nvd", - "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2019-1549", - "DataSource": { - "ID": "alpine", - "Name": "Alpine Secdb", - "URL": "https://secdb.alpinelinux.org/" - }, - "Title": "openssl: information disclosure in fork()", - "Description": "OpenSSL 1.1.1 introduced a rewritten random number generator (RNG). This was intended to include protection in the event of a fork() system call in order to ensure that the parent and child processes did not share the same RNG state. However this protection was not being used in the default case. A partial mitigation for this issue is that the output from a high precision timer is mixed into the RNG state so the likelihood of a parent and child process sharing state is significantly reduced. If an application already calls OPENSSL_init_crypto() explicitly using OPENSSL_INIT_ATFORK then this problem does not occur at all. Fixed in OpenSSL 1.1.1d (Affected 1.1.1-1.1.1c).", - "Severity": "MEDIUM", - "CweIDs": [ - "CWE-330" - ], - "VendorSeverity": { - "amazon": 2, - "nvd": 2, - "oracle-oval": 2, - "photon": 2, - "redhat": 1, - "ubuntu": 1 - }, - "CVSS": { - "nvd": { - "V2Vector": "AV:N/AC:L/Au:N/C:P/I:N/A:N", - "V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", - "V2Score": 5, - "V3Score": 5.3 - }, - "redhat": { - "V3Vector": "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N", - "V3Score": 4.8 - } - }, - "References": [ - "https://access.redhat.com/security/cve/CVE-2019-1549", - "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1549", - "https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=1b0fe00e2704b5e20334a16d3c9099d1ba2ef1be", - "https://linux.oracle.com/cve/CVE-2019-1549.html", - "https://linux.oracle.com/errata/ELSA-2020-1840.html", - "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/GY6SNRJP2S7Y42GIIDO3HXPNMDYN2U3A/", - "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/ZN4VVQJ3JDCHGIHV4Y2YTXBYQZ6PWQ7E/", - "https://seclists.org/bugtraq/2019/Oct/1", - "https://security.netapp.com/advisory/ntap-20190919-0002/", - "https://support.f5.com/csp/article/K44070243", - "https://support.f5.com/csp/article/K44070243?utm_source=f5support\u0026amp;utm_medium=RSS", - "https://ubuntu.com/security/notices/USN-4376-1", - "https://usn.ubuntu.com/4376-1/", - "https://www.debian.org/security/2019/dsa-4539", - "https://www.openssl.org/news/secadv/20190910.txt", - "https://www.oracle.com/security-alerts/cpuapr2020.html", - "https://www.oracle.com/security-alerts/cpujan2020.html", - "https://www.oracle.com/security-alerts/cpujul2020.html", - "https://www.oracle.com/security-alerts/cpuoct2020.html", - "https://www.oracle.com/technetwork/security-advisory/cpuoct2019-5072832.html" - ], - "PublishedDate": "2019-09-10T17:15:00Z", - "LastModifiedDate": "2020-10-20T22:15:00Z" - }, - { - "VulnerabilityID": "CVE-2019-1551", - "PkgID": "libcrypto1.1@1.1.1c-r0", - "PkgName": "libcrypto1.1", - "PkgIdentifier": { - "PURL": "pkg:apk/alpine/libcrypto1.1@1.1.1c-r0?arch=x86_64\u0026distro=3.10.2" - }, - "InstalledVersion": "1.1.1c-r0", - "FixedVersion": "1.1.1d-r2", - "Status": "fixed", - "Layer": { - "Digest": "sha256:9d48c3bd43c520dc2784e868a780e976b207cbf493eaff8c6596eb871cbd9609", - "DiffID": "sha256:03901b4a2ea88eeaad62dbe59b072b28b6efa00491962b8741081c5df50c65e0" - }, - "SeveritySource": "nvd", - "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2019-1551", - "DataSource": { - "ID": "alpine", - "Name": "Alpine Secdb", - "URL": "https://secdb.alpinelinux.org/" - }, - "Title": "openssl: Integer overflow in RSAZ modular exponentiation on x86_64", - "Description": "There is an overflow bug in the x64_64 Montgomery squaring procedure used in exponentiation with 512-bit moduli. No EC algorithms are affected. Analysis suggests that attacks against 2-prime RSA1024, 3-prime RSA1536, and DSA1024 as a result of this defect would be very difficult to perform and are not believed likely. Attacks against DH512 are considered just feasible. However, for an attack the target would have to re-use the DH512 private key, which is not recommended anyway. Also applications directly using the low level API BN_mod_exp may be affected if they use BN_FLG_CONSTTIME. Fixed in OpenSSL 1.1.1e (Affected 1.1.1-1.1.1d). Fixed in OpenSSL 1.0.2u (Affected 1.0.2-1.0.2t).", - "Severity": "MEDIUM", - "CweIDs": [ - "CWE-200" - ], - "VendorSeverity": { - "amazon": 1, - "nvd": 2, - "oracle-oval": 1, - "photon": 2, - "redhat": 1, - "ubuntu": 1 - }, - "CVSS": { - "nvd": { - "V2Vector": "AV:N/AC:L/Au:N/C:P/I:N/A:N", - "V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", - "V2Score": 5, - "V3Score": 5.3 - }, - "redhat": { - "V3Vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N", - "V3Score": 4.8 - } - }, - "References": [ - "http://lists.opensuse.org/opensuse-security-announce/2020-01/msg00030.html", - "http://packetstormsecurity.com/files/155754/Slackware-Security-Advisory-openssl-Updates.html", - "https://access.redhat.com/security/cve/CVE-2019-1551", - "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1551", - "https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=419102400a2811582a7a3d4a4e317d72e5ce0a8f", - "https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=f1c5eea8a817075d31e43f5876993c6710238c98", - "https://github.com/openssl/openssl/pull/10575", - "https://linux.oracle.com/cve/CVE-2019-1551.html", - "https://linux.oracle.com/errata/ELSA-2020-4514.html", - "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/DDHOAATPWJCXRNFMJ2SASDBBNU5RJONY/", - "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/EXDDAOWSAIEFQNBHWYE6PPYFV4QXGMCD/", - "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/XVEP3LAK4JSPRXFO4QF4GG2IVXADV3SO/", - "https://seclists.org/bugtraq/2019/Dec/39", - "https://seclists.org/bugtraq/2019/Dec/46", - "https://security.gentoo.org/glsa/202004-10", - "https://security.netapp.com/advisory/ntap-20191210-0001/", - "https://ubuntu.com/security/notices/USN-4376-1", - "https://ubuntu.com/security/notices/USN-4504-1", - "https://usn.ubuntu.com/4376-1/", - "https://usn.ubuntu.com/4504-1/", - "https://www.debian.org/security/2019/dsa-4594", - "https://www.debian.org/security/2021/dsa-4855", - "https://www.openssl.org/news/secadv/20191206.txt", - "https://www.oracle.com/security-alerts/cpuApr2021.html", - "https://www.oracle.com/security-alerts/cpujan2021.html", - "https://www.oracle.com/security-alerts/cpujul2020.html", - "https://www.tenable.com/security/tns-2019-09", - "https://www.tenable.com/security/tns-2020-03", - "https://www.tenable.com/security/tns-2020-11", - "https://www.tenable.com/security/tns-2021-10" - ], - "PublishedDate": "2019-12-06T18:15:00Z", - "LastModifiedDate": "2021-07-21T11:39:00Z" - }, - { - "VulnerabilityID": "CVE-2019-1549", - "PkgID": "libssl1.1@1.1.1c-r0", - "PkgName": "libssl1.1", - "PkgIdentifier": { - "PURL": "pkg:apk/alpine/libssl1.1@1.1.1c-r0?arch=x86_64\u0026distro=3.10.2" - }, - "InstalledVersion": "1.1.1c-r0", - "FixedVersion": "1.1.1d-r0", - "Status": "fixed", - "Layer": { - "Digest": "sha256:9d48c3bd43c520dc2784e868a780e976b207cbf493eaff8c6596eb871cbd9609", - "DiffID": "sha256:03901b4a2ea88eeaad62dbe59b072b28b6efa00491962b8741081c5df50c65e0" - }, - "SeveritySource": "nvd", - "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2019-1549", - "DataSource": { - "ID": "alpine", - "Name": "Alpine Secdb", - "URL": "https://secdb.alpinelinux.org/" - }, - "Title": "openssl: information disclosure in fork()", - "Description": "OpenSSL 1.1.1 introduced a rewritten random number generator (RNG). This was intended to include protection in the event of a fork() system call in order to ensure that the parent and child processes did not share the same RNG state. However this protection was not being used in the default case. A partial mitigation for this issue is that the output from a high precision timer is mixed into the RNG state so the likelihood of a parent and child process sharing state is significantly reduced. If an application already calls OPENSSL_init_crypto() explicitly using OPENSSL_INIT_ATFORK then this problem does not occur at all. Fixed in OpenSSL 1.1.1d (Affected 1.1.1-1.1.1c).", - "Severity": "MEDIUM", - "CweIDs": [ - "CWE-330" - ], - "VendorSeverity": { - "amazon": 2, - "nvd": 2, - "oracle-oval": 2, - "photon": 2, - "redhat": 1, - "ubuntu": 1 - }, - "CVSS": { - "nvd": { - "V2Vector": "AV:N/AC:L/Au:N/C:P/I:N/A:N", - "V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", - "V2Score": 5, - "V3Score": 5.3 - }, - "redhat": { - "V3Vector": "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N", - "V3Score": 4.8 - } - }, - "References": [ - "https://access.redhat.com/security/cve/CVE-2019-1549", - "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1549", - "https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=1b0fe00e2704b5e20334a16d3c9099d1ba2ef1be", - "https://linux.oracle.com/cve/CVE-2019-1549.html", - "https://linux.oracle.com/errata/ELSA-2020-1840.html", - "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/GY6SNRJP2S7Y42GIIDO3HXPNMDYN2U3A/", - "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/ZN4VVQJ3JDCHGIHV4Y2YTXBYQZ6PWQ7E/", - "https://seclists.org/bugtraq/2019/Oct/1", - "https://security.netapp.com/advisory/ntap-20190919-0002/", - "https://support.f5.com/csp/article/K44070243", - "https://support.f5.com/csp/article/K44070243?utm_source=f5support\u0026amp;utm_medium=RSS", - "https://ubuntu.com/security/notices/USN-4376-1", - "https://usn.ubuntu.com/4376-1/", - "https://www.debian.org/security/2019/dsa-4539", - "https://www.openssl.org/news/secadv/20190910.txt", - "https://www.oracle.com/security-alerts/cpuapr2020.html", - "https://www.oracle.com/security-alerts/cpujan2020.html", - "https://www.oracle.com/security-alerts/cpujul2020.html", - "https://www.oracle.com/security-alerts/cpuoct2020.html", - "https://www.oracle.com/technetwork/security-advisory/cpuoct2019-5072832.html" - ], - "PublishedDate": "2019-09-10T17:15:00Z", - "LastModifiedDate": "2020-10-20T22:15:00Z" - }, - { - "VulnerabilityID": "CVE-2019-1551", - "PkgID": "libssl1.1@1.1.1c-r0", - "PkgName": "libssl1.1", - "PkgIdentifier": { - "PURL": "pkg:apk/alpine/libssl1.1@1.1.1c-r0?arch=x86_64\u0026distro=3.10.2" - }, - "InstalledVersion": "1.1.1c-r0", - "FixedVersion": "1.1.1d-r2", - "Status": "fixed", - "Layer": { - "Digest": "sha256:9d48c3bd43c520dc2784e868a780e976b207cbf493eaff8c6596eb871cbd9609", - "DiffID": "sha256:03901b4a2ea88eeaad62dbe59b072b28b6efa00491962b8741081c5df50c65e0" - }, - "SeveritySource": "nvd", - "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2019-1551", - "DataSource": { - "ID": "alpine", - "Name": "Alpine Secdb", - "URL": "https://secdb.alpinelinux.org/" - }, - "Title": "openssl: Integer overflow in RSAZ modular exponentiation on x86_64", - "Description": "There is an overflow bug in the x64_64 Montgomery squaring procedure used in exponentiation with 512-bit moduli. No EC algorithms are affected. Analysis suggests that attacks against 2-prime RSA1024, 3-prime RSA1536, and DSA1024 as a result of this defect would be very difficult to perform and are not believed likely. Attacks against DH512 are considered just feasible. However, for an attack the target would have to re-use the DH512 private key, which is not recommended anyway. Also applications directly using the low level API BN_mod_exp may be affected if they use BN_FLG_CONSTTIME. Fixed in OpenSSL 1.1.1e (Affected 1.1.1-1.1.1d). Fixed in OpenSSL 1.0.2u (Affected 1.0.2-1.0.2t).", - "Severity": "MEDIUM", - "CweIDs": [ - "CWE-200" - ], - "VendorSeverity": { - "amazon": 1, - "nvd": 2, - "oracle-oval": 1, - "photon": 2, - "redhat": 1, - "ubuntu": 1 - }, - "CVSS": { - "nvd": { - "V2Vector": "AV:N/AC:L/Au:N/C:P/I:N/A:N", - "V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", - "V2Score": 5, - "V3Score": 5.3 - }, - "redhat": { - "V3Vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N", - "V3Score": 4.8 - } - }, - "References": [ - "http://lists.opensuse.org/opensuse-security-announce/2020-01/msg00030.html", - "http://packetstormsecurity.com/files/155754/Slackware-Security-Advisory-openssl-Updates.html", - "https://access.redhat.com/security/cve/CVE-2019-1551", - "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1551", - "https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=419102400a2811582a7a3d4a4e317d72e5ce0a8f", - "https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=f1c5eea8a817075d31e43f5876993c6710238c98", - "https://github.com/openssl/openssl/pull/10575", - "https://linux.oracle.com/cve/CVE-2019-1551.html", - "https://linux.oracle.com/errata/ELSA-2020-4514.html", - "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/DDHOAATPWJCXRNFMJ2SASDBBNU5RJONY/", - "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/EXDDAOWSAIEFQNBHWYE6PPYFV4QXGMCD/", - "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/XVEP3LAK4JSPRXFO4QF4GG2IVXADV3SO/", - "https://seclists.org/bugtraq/2019/Dec/39", - "https://seclists.org/bugtraq/2019/Dec/46", - "https://security.gentoo.org/glsa/202004-10", - "https://security.netapp.com/advisory/ntap-20191210-0001/", - "https://ubuntu.com/security/notices/USN-4376-1", - "https://ubuntu.com/security/notices/USN-4504-1", - "https://usn.ubuntu.com/4376-1/", - "https://usn.ubuntu.com/4504-1/", - "https://www.debian.org/security/2019/dsa-4594", - "https://www.debian.org/security/2021/dsa-4855", - "https://www.openssl.org/news/secadv/20191206.txt", - "https://www.oracle.com/security-alerts/cpuApr2021.html", - "https://www.oracle.com/security-alerts/cpujan2021.html", - "https://www.oracle.com/security-alerts/cpujul2020.html", - "https://www.tenable.com/security/tns-2019-09", - "https://www.tenable.com/security/tns-2020-03", - "https://www.tenable.com/security/tns-2020-11", - "https://www.tenable.com/security/tns-2021-10" - ], - "PublishedDate": "2019-12-06T18:15:00Z", - "LastModifiedDate": "2021-07-21T11:39:00Z" - } - ] - } - ] -} diff --git a/pkg/fanal/test/integration/library_test.go b/pkg/fanal/test/integration/library_test.go index cf7ed95a1679..ea76c7965b3a 100644 --- a/pkg/fanal/test/integration/library_test.go +++ b/pkg/fanal/test/integration/library_test.go @@ -139,54 +139,6 @@ var tests = []testCase{ }, } -func TestFanal_Library_DockerLessMode(t *testing.T) { - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - ctx := context.Background() - d := t.TempDir() - - c, err := cache.NewFSCache(d) - require.NoError(t, err, tt.name) - - cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - require.NoError(t, err) - - // remove existing Image if any - _, _ = cli.ImageRemove(ctx, tt.remoteImageName, dimage.RemoveOptions{ - Force: true, - PruneChildren: true, - }) - - // Enable only registry scanning - img, cleanup, err := image.NewContainerImage(ctx, tt.remoteImageName, types.ImageOptions{ - ImageSources: types.ImageSources{types.RemoteImageSource}, - }) - require.NoError(t, err) - defer cleanup() - - // don't scan licenses in the test - in parallel it will fail - ar, err := aimage.NewArtifact(img, c, artifact.Option{ - DisabledAnalyzers: []analyzer.Type{ - analyzer.TypeExecutable, - analyzer.TypeLicenseFile, - }, - }) - require.NoError(t, err) - - applier := applier.NewApplier(c) - - // run tests twice, one without cache and with cache - for i := 1; i <= 2; i++ { - runChecks(t, ctx, ar, applier, tt) - } - - // clear Cache - require.NoError(t, c.Clear()) - }) - } -} - func TestFanal_Library_DockerMode(t *testing.T) { // Disable updating golden files because local images don't have compressed layer digests, // and updating golden files in this function results in incomplete files. From ea0cf0379aff0348fde87356dab37947800fc1b6 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Sat, 28 Sep 2024 11:06:02 +0600 Subject: [PATCH 15/94] fix(misconf): escape all special sequences (#7558) Signed-off-by: nikpivkin --- pkg/iac/terraform/resource_block.go | 40 +++++++++++---- pkg/iac/terraform/resource_block_test.go | 62 ++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 pkg/iac/terraform/resource_block_test.go diff --git a/pkg/iac/terraform/resource_block.go b/pkg/iac/terraform/resource_block.go index 339843423112..abce0fcb040e 100644 --- a/pkg/iac/terraform/resource_block.go +++ b/pkg/iac/terraform/resource_block.go @@ -3,7 +3,6 @@ package terraform import ( "bytes" "fmt" - "regexp" "strings" "text/template" ) @@ -106,19 +105,14 @@ func renderPrimitive(val any) string { func parseStringPrimitive(input string) string { // we must escape templating // ref: https://developer.hashicorp.com/terraform/language/expressions/strings#escape-sequences-1 - r := regexp.MustCompile(`((\$|\%)\{.+\})`) - ff := r.ReplaceAllStringFunc(input, func(s string) string { - s = strings.Replace(s, "$", "$$", 1) - s = strings.Replace(s, "%", "%%", 1) - return s - }) - if strings.Contains(ff, "\n") { + input = escapeSpecialSequences(input) + if strings.Contains(input, "\n") { return fmt.Sprintf(`< 0 && rune(input[i-1]) == r { + continue + } + + sb.WriteRune(r) + } else { + sb.WriteRune(r) + } + } + return sb.String() +} diff --git a/pkg/iac/terraform/resource_block_test.go b/pkg/iac/terraform/resource_block_test.go new file mode 100644 index 000000000000..37fb1d32fdcb --- /dev/null +++ b/pkg/iac/terraform/resource_block_test.go @@ -0,0 +1,62 @@ +package terraform + +import ( + "testing" + + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclsyntax" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_EscapeSpecialSequences(t *testing.T) { + tests := []struct { + name string + inp string + expected string + }{ + { + name: "without special sequences", + inp: `"hello world\\"`, + expected: `"hello world\\"`, + }, + { + name: "interpolation", + inp: `"Hello, ${var.name}!"`, + expected: `"Hello, $${var.name}!"`, + }, + { + name: "directive", + inp: `"Hello, %{ if true }foo%{ else }bar%{ endif }!"`, + expected: `"Hello, %%{ if true }foo%%{ else }bar%%{ endif }!"`, + }, + { + name: "interpolation already escaped", + inp: `"Hello, $${var.name}!"`, + expected: `"Hello, $${var.name}!"`, + }, + { + name: "start with special character", + inp: `${var.name}!"`, + expected: `$${var.name}!"`, + }, + { + name: "grok pattern", + inp: "# Grok Pattern Template\ngrok_pattern = \"%{TIMESTAMP_ISO8601:time} \\\\[%{NUMBER:pid}\\\\] %{GREEDYDATA:message}\"", + expected: "# Grok Pattern Template\ngrok_pattern = \"%%{TIMESTAMP_ISO8601:time} \\\\[%%{NUMBER:pid}\\\\] %%{GREEDYDATA:message}\"", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := escapeSpecialSequences(tt.inp) + assert.Equal(t, tt.expected, got) + + // We make sure that the characters are properly escaped + _, diag := hclsyntax.ParseTemplate([]byte(got), "", hcl.InitialPos) + if diag.HasErrors() { + require.NoError(t, diag) + } + }) + } +} From ef0a27d515ff80762bf1959d44a8bde017ae06ec Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Sat, 28 Sep 2024 12:31:53 +0600 Subject: [PATCH 16/94] feat(misconf): add ability to disable checks by ID (#7536) Signed-off-by: nikpivkin Co-authored-by: Simar --- pkg/iac/rego/load.go | 6 +++ pkg/iac/rego/options.go | 11 +++++ pkg/iac/rego/scanner.go | 15 ++++--- pkg/iac/rego/scanner_test.go | 84 ++++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 6 deletions(-) diff --git a/pkg/iac/rego/load.go b/pkg/iac/rego/load.go index a1c29d163fae..8f1033ecfa2d 100644 --- a/pkg/iac/rego/load.go +++ b/pkg/iac/rego/load.go @@ -295,6 +295,12 @@ func (s *Scanner) filterModules(retriever *MetadataRetriever) error { continue } + if IsBuiltinNamespace(getModuleNamespace(module)) { + if _, disabled := s.disabledCheckIDs[meta.ID]; disabled { // ignore builtin disabled checks + continue + } + } + if len(meta.InputOptions.Selectors) == 0 { s.logger.Warn( "Module has no input selectors - it will be loaded for all inputs!", diff --git a/pkg/iac/rego/options.go b/pkg/iac/rego/options.go index d4b622a68c16..5cc60284abdb 100644 --- a/pkg/iac/rego/options.go +++ b/pkg/iac/rego/options.go @@ -106,3 +106,14 @@ func WithCustomSchemas(schemas map[string][]byte) options.ScannerOption { } } } + +// WithDisabledCheckIDs disables checks by their ID (ID field in metadata) +func WithDisabledCheckIDs(ids ...string) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + for _, id := range ids { + ss.disabledCheckIDs[id] = struct{}{} + } + } + } +} diff --git a/pkg/iac/rego/scanner.go b/pkg/iac/rego/scanner.go index a8e1caf525b3..9cf80fc83da0 100644 --- a/pkg/iac/rego/scanner.go +++ b/pkg/iac/rego/scanner.go @@ -69,6 +69,8 @@ type Scanner struct { embeddedLibs map[string]*ast.Module embeddedChecks map[string]*ast.Module customSchemas map[string][]byte + + disabledCheckIDs map[string]struct{} } func (s *Scanner) SetIncludeDeprecatedChecks(b bool) { @@ -109,12 +111,13 @@ func NewScanner(source types.Source, opts ...options.ScannerOption) *Scanner { } s := &Scanner{ - regoErrorLimit: ast.CompileErrorLimitDefault, - sourceType: source, - ruleNamespaces: make(map[string]struct{}), - runtimeValues: addRuntimeValues(), - logger: log.WithPrefix("rego"), - customSchemas: make(map[string][]byte), + regoErrorLimit: ast.CompileErrorLimitDefault, + sourceType: source, + ruleNamespaces: make(map[string]struct{}), + runtimeValues: addRuntimeValues(), + logger: log.WithPrefix("rego"), + customSchemas: make(map[string][]byte), + disabledCheckIDs: make(map[string]struct{}), } maps.Copy(s.ruleNamespaces, builtinNamespaces) diff --git a/pkg/iac/rego/scanner_test.go b/pkg/iac/rego/scanner_test.go index 73ef55223f14..1310e56d2ec4 100644 --- a/pkg/iac/rego/scanner_test.go +++ b/pkg/iac/rego/scanner_test.go @@ -1153,3 +1153,87 @@ deny { }) } } + +func Test_RegoScanner_WithDisabledCheckIDs(t *testing.T) { + + check := `# METADATA +# custom: +# id: TEST-001 +# avd_id: AVD-TEST-001 +# severity: LOW +# provider: aws +# service: s3 +# short_code: test +package builtin.test + +deny { + true +} +` + + tests := []struct { + name string + disabledChecks []string + inputCheck string + expected bool + }{ + { + name: "no disabled checks", + expected: true, + inputCheck: check, + }, + { + name: "disable check by ID", + disabledChecks: []string{"TEST-001"}, + inputCheck: check, + }, + { + name: "disabling a non-existent check", + disabledChecks: []string{"FOO"}, + expected: true, + inputCheck: check, + }, + { + name: "one of the identifiers does not exist", + disabledChecks: []string{"FOO", "TEST-001"}, + inputCheck: check, + }, + { + name: "do not disable user checks with builtin IDs", + inputCheck: `# METADATA +# custom: +# id: TEST-001 +# avd_id: AVD-TEST-001 +# severity: LOW +# provider: aws +# service: s3 +# short_code: test +package user.test + +deny { + true +} +`, + disabledChecks: []string{"TEST-001"}, + expected: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + scanner := rego.NewScanner( + types.SourceYAML, + rego.WithPolicyReader(strings.NewReader(tt.inputCheck)), + rego.WithDisabledCheckIDs(tt.disabledChecks...), + rego.WithPolicyNamespaces("user"), + ) + + require.NoError(t, scanner.LoadPolicies(nil)) + results, err := scanner.ScanInput(context.TODO(), rego.Input{}) + require.NoError(t, err) + + require.Equal(t, tt.expected, len(results.GetFailed()) > 0) + }) + } +} From efdb68d3b9ddf9dfaf45ea5855b31c43a4366bab Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Sun, 29 Sep 2024 20:23:34 +0200 Subject: [PATCH 17/94] feat(suse): added SUSE Linux Enterprise Micro support (#7294) Signed-off-by: Marcus Meissner Signed-off-by: knqyf263 Co-authored-by: knqyf263 --- docs/docs/coverage/os/index.md | 3 +- docs/docs/coverage/os/suse.md | 3 +- integration/client_server_test.go | 7 + integration/docker_engine_test.go | 6 + integration/standalone_tar_test.go | 8 + integration/testdata/fixtures/db/suse.yaml | 19 ++ .../testdata/fixtures/db/vulnerability.yaml | 9 + .../testdata/opensuse-leap-151.json.golden | 4 +- .../testdata/opensuse-tumbleweed.json.golden | 2 +- .../testdata/sl-micro-rancher5.4.json.golden | 69 +++++ pkg/detector/ospkg/detect.go | 1 + pkg/detector/ospkg/suse/suse.go | 21 ++ pkg/detector/ospkg/suse/suse_test.go | 80 ++++++ .../suse/testdata/fixtures/data-source.yaml | 5 + .../ospkg/suse/testdata/fixtures/suse.yaml | 20 ++ pkg/fanal/analyzer/os/release/release.go | 5 + pkg/fanal/analyzer/os/release/release_test.go | 30 +++ .../analyzer/os/release/testdata/slemicro | 8 + .../os/release/testdata/slemicro-rancher | 13 + .../analyzer/os/release/testdata/slemicro6.0 | 10 + .../packages/opensuse-tumbleweed.json.golden | 252 +++++++++--------- pkg/fanal/types/const.go | 1 + pkg/purl/purl.go | 13 +- 23 files changed, 453 insertions(+), 136 deletions(-) create mode 100644 integration/testdata/fixtures/db/suse.yaml create mode 100644 integration/testdata/sl-micro-rancher5.4.json.golden create mode 100644 pkg/fanal/analyzer/os/release/testdata/slemicro create mode 100644 pkg/fanal/analyzer/os/release/testdata/slemicro-rancher create mode 100644 pkg/fanal/analyzer/os/release/testdata/slemicro6.0 diff --git a/docs/docs/coverage/os/index.md b/docs/docs/coverage/os/index.md index a28e113f07c9..a49793db8124 100644 --- a/docs/docs/coverage/os/index.md +++ b/docs/docs/coverage/os/index.md @@ -23,7 +23,8 @@ Trivy supports operating systems for | [Amazon Linux](amazon.md) | 1, 2, 2023 | dnf/yum/rpm | | [openSUSE Leap](suse.md) | 42, 15 | zypper/rpm | | [openSUSE Tumbleweed](suse.md) | (n/a) | zypper/rpm | -| [SUSE Enterprise Linux](suse.md) | 11, 12, 15 | zypper/rpm | +| [SUSE Linux Enterprise](suse.md) | 11, 12, 15 | zypper/rpm | +| [SUSE Linux Enterprise Micro](suse.md)| 5, 6 | zypper/rpm | | [Photon OS](photon.md) | 1.0, 2.0, 3.0, 4.0 | tndf/yum/rpm | | [Debian GNU/Linux](debian.md) | 7, 8, 9, 10, 11, 12 | apt/dpkg | | [Ubuntu](ubuntu.md) | All versions supported by Canonical | apt/dpkg | diff --git a/docs/docs/coverage/os/suse.md b/docs/docs/coverage/os/suse.md index 15cfb1e9379a..b28fed13425b 100644 --- a/docs/docs/coverage/os/suse.md +++ b/docs/docs/coverage/os/suse.md @@ -3,7 +3,8 @@ Trivy supports the following distributions: - openSUSE Leap - openSUSE Tumbleweed -- SUSE Enterprise Linux (SLE) +- SUSE Linux Enterprise (SLE) +- SUSE Linux Enterprise Micro Please see [here](index.md#supported-os) for supported versions. diff --git a/integration/client_server_test.go b/integration/client_server_test.go index adeab3f4c7b3..07a4f086200c 100644 --- a/integration/client_server_test.go +++ b/integration/client_server_test.go @@ -220,6 +220,13 @@ func TestClientServer(t *testing.T) { }, golden: "testdata/opensuse-tumbleweed.json.golden", }, + { + name: "sle micro rancher 5.4", + args: csArgs{ + Input: "testdata/fixtures/images/sle-micro-rancher-5.4_ndb.tar.gz", + }, + golden: "testdata/sl-micro-rancher5.4.json.golden", + }, { name: "photon 3.0", args: csArgs{ diff --git a/integration/docker_engine_test.go b/integration/docker_engine_test.go index 5b62d391eead..7f9a3119a156 100644 --- a/integration/docker_engine_test.go +++ b/integration/docker_engine_test.go @@ -198,6 +198,12 @@ func TestDockerEngine(t *testing.T) { input: "testdata/fixtures/images/opensuse-tumbleweed.tar.gz", golden: "testdata/opensuse-tumbleweed.json.golden", }, + { + name: "sle micro rancher 5.4", + imageTag: "ghcr.io/aquasecurity/trivy-test-images:sle-micro-rancher-5.4_ndb", + input: "testdata/fixtures/images/sle-micro-rancher-5.4_ndb.tar.gz", + golden: "testdata/sl-micro-rancher5.4.json.golden", + }, { name: "photon 3.0", imageTag: "ghcr.io/aquasecurity/trivy-test-images:photon-30", diff --git a/integration/standalone_tar_test.go b/integration/standalone_tar_test.go index dce852cf7f3c..039293cbfd56 100644 --- a/integration/standalone_tar_test.go +++ b/integration/standalone_tar_test.go @@ -341,6 +341,14 @@ func TestTar(t *testing.T) { }, golden: "testdata/opensuse-tumbleweed.json.golden", }, + { + name: "sle micro rancher 5.4", + args: args{ + Format: types.FormatJSON, + Input: "testdata/fixtures/images/sle-micro-rancher-5.4_ndb.tar.gz", + }, + golden: "testdata/sl-micro-rancher5.4.json.golden", + }, { name: "photon 3.0", args: args{ diff --git a/integration/testdata/fixtures/db/suse.yaml b/integration/testdata/fixtures/db/suse.yaml new file mode 100644 index 000000000000..690360c5de13 --- /dev/null +++ b/integration/testdata/fixtures/db/suse.yaml @@ -0,0 +1,19 @@ +- bucket: "SUSE Linux Enterprise 15-SP3" + pairs: + - bucket: libopenssl1_1 + pairs: + - key: "SUSE-SU-2022:2251-1" + value: + FixedVersion: 1.1.1d-150200.11.48.1 + - bucket: openssl-1_1 + pairs: + - key: "SUSE-SU-2022:2251-1" + value: + FixedVersion: 1.1.1d-150200.11.48.1 +- bucket: "SUSE Linux Enterprise Micro 5.3" + pairs: + - bucket: libopenssl1_1 + pairs: + - key: "SUSE-SU-2023:0311-1" + value: + FixedVersion: 1.1.1l-150400.7.22.1 diff --git a/integration/testdata/fixtures/db/vulnerability.yaml b/integration/testdata/fixtures/db/vulnerability.yaml index 6fcdcece75bd..e18d731a30c8 100644 --- a/integration/testdata/fixtures/db/vulnerability.yaml +++ b/integration/testdata/fixtures/db/vulnerability.yaml @@ -1349,6 +1349,15 @@ - "https://www.suse.com/security/cve/CVE-2023-2975/" - "https://www.suse.com/security/cve/CVE-2023-3446/" - "https://www.suse.com/support/security/rating/" + - key: SUSE-SU-2022:2251-1 + value: + Title: "Security update for openssl-1_1" + Description: "This update for openssl-1_1 fixes the following issues:\nCVE-2022-1292: Fixed command injection in c_rehash (bsc#1199166).\nCVE-2022-2068: Fixed more shell code injection issues in c_rehash. (bsc#1200550)" + Severity: MEDIUM + References: + - "https://www.suse.com/security/cve/CVE-2022-1292/" + - "https://www.suse.com/security/cve/CVE-2022-2068/" + - "https://www.suse.com/support/security/rating/" - key: CVE-2022-22965 value: Title: "spring-framework: RCE via Data Binding on JDK 9+" diff --git a/integration/testdata/opensuse-leap-151.json.golden b/integration/testdata/opensuse-leap-151.json.golden index 77b0148604bb..dadc7adcf600 100644 --- a/integration/testdata/opensuse-leap-151.json.golden +++ b/integration/testdata/opensuse-leap-151.json.golden @@ -66,7 +66,7 @@ "PkgID": "libopenssl1_1@1.1.0i-lp151.8.3.1.x86_64", "PkgName": "libopenssl1_1", "PkgIdentifier": { - "PURL": "pkg:rpm/opensuse.leap/libopenssl1_1@1.1.0i-lp151.8.3.1?arch=x86_64\u0026distro=opensuse.leap-15.1", + "PURL": "pkg:rpm/opensuse/libopenssl1_1@1.1.0i-lp151.8.3.1?arch=x86_64\u0026distro=opensuse.leap-15.1", "UID": "898b73ddd0412f57" }, "InstalledVersion": "1.1.0i-lp151.8.3.1", @@ -99,7 +99,7 @@ "PkgID": "openssl-1_1@1.1.0i-lp151.8.3.1.x86_64", "PkgName": "openssl-1_1", "PkgIdentifier": { - "PURL": "pkg:rpm/opensuse.leap/openssl-1_1@1.1.0i-lp151.8.3.1?arch=x86_64\u0026distro=opensuse.leap-15.1", + "PURL": "pkg:rpm/opensuse/openssl-1_1@1.1.0i-lp151.8.3.1?arch=x86_64\u0026distro=opensuse.leap-15.1", "UID": "58980d005de43f54" }, "InstalledVersion": "1.1.0i-lp151.8.3.1", diff --git a/integration/testdata/opensuse-tumbleweed.json.golden b/integration/testdata/opensuse-tumbleweed.json.golden index b3dc552bdfca..a15146616bc2 100644 --- a/integration/testdata/opensuse-tumbleweed.json.golden +++ b/integration/testdata/opensuse-tumbleweed.json.golden @@ -69,7 +69,7 @@ "PkgID": "libopenssl3@3.1.4-9.1.x86_64", "PkgName": "libopenssl3", "PkgIdentifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libopenssl3@3.1.4-9.1?arch=x86_64\u0026distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libopenssl3@3.1.4-9.1?arch=x86_64\u0026distro=opensuse.tumbleweed-20240607", "UID": "f051425f385d2b99" }, "InstalledVersion": "3.1.4-9.1", diff --git a/integration/testdata/sl-micro-rancher5.4.json.golden b/integration/testdata/sl-micro-rancher5.4.json.golden new file mode 100644 index 000000000000..99e2ad4ca599 --- /dev/null +++ b/integration/testdata/sl-micro-rancher5.4.json.golden @@ -0,0 +1,69 @@ +{ + "SchemaVersion": 2, + "CreatedAt": "2021-08-25T12:20:30.000000005Z", + "ArtifactName": "testdata/fixtures/images/sle-micro-rancher-5.4_ndb.tar.gz", + "ArtifactType": "container_image", + "Metadata": { + "OS": { + "Family": "suse linux enterprise micro", + "Name": "5.4" + }, + "ImageID": "sha256:c45ec974938acac29c893b5d273d73e4ebdd7e6a97b6fa861dfbd8dd430b9016", + "DiffIDs": [ + "sha256:7cdd3aec849d122d63dc83a5e1e2fb89b341c67b03e25979131ca335a463bb57" + ], + "ImageConfig": { + "architecture": "amd64", + "author": "SUSE LLC (https://www.suse.com/)", + "created": "2024-09-03T17:54:39Z", + "history": [ + { + "author": "SUSE LLC \u003chttps://www.suse.com/\u003e", + "created": "2024-09-03T17:54:39Z", + "created_by": "KIWI 9.24.43" + } + ], + "os": "linux", + "rootfs": { + "type": "layers", + "diff_ids": [ + "sha256:7cdd3aec849d122d63dc83a5e1e2fb89b341c67b03e25979131ca335a463bb57" + ] + }, + "config": { + "Cmd": [ + "/bin/bash" + ], + "Labels": { + "com.suse.eula": "sle-eula", + "com.suse.image-type": "sle-micro", + "com.suse.release-stage": "released", + "com.suse.sle.micro.rancher.created": "2024-09-03T17:53:32.129328086Z", + "com.suse.sle.micro.rancher.description": "Image containing a micro environment for containers based on the SLE Micro for Rancher.", + "com.suse.sle.micro.rancher.disturl": "obs://build.suse.de/SUSE:SLE-15-SP4:Update:Products:Micro54:Update:CR/images/fcaa3a91b132f1955fa900b902aef7f2-SLE-Micro-Rancher", + "com.suse.sle.micro.rancher.reference": "registry.suse.com/suse/sle-micro-rancher/5.4:%PKG_VERSION%-%RELEASE", + "com.suse.sle.micro.rancher.title": "SLE Micro for Rancher Base Container", + "com.suse.sle.micro.rancher.url": "https://www.suse.com/products/micro/", + "com.suse.sle.micro.rancher.vendor": "SUSE LLC", + "com.suse.sle.micro.rancher.version": "5.4", + "com.suse.supportlevel": "l3", + "org.openbuildservice.disturl": "obs://build.suse.de/SUSE:SLE-15-SP4:Update:Products:Micro54:Update:CR/images/fcaa3a91b132f1955fa900b902aef7f2-SLE-Micro-Rancher", + "org.opencontainers.image.created": "2024-09-03T17:53:32.129328086Z", + "org.opencontainers.image.description": "Image containing a micro environment for containers based on the SLE Micro for Rancher.", + "org.opencontainers.image.title": "SLE Micro for Rancher Base Container", + "org.opencontainers.image.url": "https://www.suse.com/products/micro/", + "org.opencontainers.image.vendor": "SUSE LLC", + "org.opencontainers.image.version": "5.4", + "org.suse.reference": "registry.suse.com/suse/sle-micro-rancher/5.4:%PKG_VERSION%-%RELEASE" + } + } + } + }, + "Results": [ + { + "Target": "testdata/fixtures/images/sle-micro-rancher-5.4_ndb.tar.gz (suse linux enterprise micro 5.4)", + "Class": "os-pkgs", + "Type": "suse linux enterprise micro" + } + ] +} diff --git a/pkg/detector/ospkg/detect.go b/pkg/detector/ospkg/detect.go index 0f4a1df2a9d3..fedc8d31c9c2 100644 --- a/pkg/detector/ospkg/detect.go +++ b/pkg/detector/ospkg/detect.go @@ -44,6 +44,7 @@ var ( ftypes.OpenSUSETumbleweed: suse.NewScanner(suse.OpenSUSETumbleweed), ftypes.OpenSUSELeap: suse.NewScanner(suse.OpenSUSE), ftypes.SLES: suse.NewScanner(suse.SUSEEnterpriseLinux), + ftypes.SLEMicro: suse.NewScanner(suse.SUSEEnterpriseLinuxMicro), ftypes.Photon: photon.NewScanner(), ftypes.Wolfi: wolfi.NewScanner(), ftypes.Chainguard: chainguard.NewScanner(), diff --git a/pkg/detector/ospkg/suse/suse.go b/pkg/detector/ospkg/suse/suse.go index b999e1dafb22..36a26b335a96 100644 --- a/pkg/detector/ospkg/suse/suse.go +++ b/pkg/detector/ospkg/suse/suse.go @@ -44,6 +44,18 @@ var ( // 6 months after SLES 15 SP7 release // "15.7": time.Date(2031, 7, 31, 23, 59, 59, 0, time.UTC), } + slemicroEolDates = map[string]time.Time{ + // Source: https://www.suse.com/lifecycle/ + "5.0": time.Date(2022, 3, 31, 23, 59, 59, 0, time.UTC), + "5.1": time.Date(2025, 10, 31, 23, 59, 59, 0, time.UTC), + "5.2": time.Date(2026, 4, 30, 23, 59, 59, 0, time.UTC), + "5.3": time.Date(2026, 10, 30, 23, 59, 59, 0, time.UTC), + "5.4": time.Date(2027, 4, 30, 23, 59, 59, 0, time.UTC), + "5.5": time.Date(2027, 10, 31, 23, 59, 59, 0, time.UTC), + "6.0": time.Date(2028, 6, 30, 23, 59, 59, 0, time.UTC), + // 6.1 will be released late 2024 + // "6.1": time.Date(2028, 11, 30, 23, 59, 59, 0, time.UTC), + } opensuseEolDates = map[string]time.Time{ // Source: https://en.opensuse.org/Lifetime @@ -66,6 +78,8 @@ type Type int const ( // SUSEEnterpriseLinux is Linux Enterprise version SUSEEnterpriseLinux Type = iota + // SUSE Linux Enterprise Micro is the micro series + SUSEEnterpriseLinuxMicro // OpenSUSE for open versions OpenSUSE OpenSUSETumbleweed @@ -83,6 +97,10 @@ func NewScanner(t Type) *Scanner { return &Scanner{ vs: susecvrf.NewVulnSrc(susecvrf.SUSEEnterpriseLinux), } + case SUSEEnterpriseLinuxMicro: + return &Scanner{ + vs: susecvrf.NewVulnSrc(susecvrf.SUSEEnterpriseLinuxMicro), + } case OpenSUSE: return &Scanner{ vs: susecvrf.NewVulnSrc(susecvrf.OpenSUSE), @@ -135,6 +153,9 @@ func (s *Scanner) IsSupportedVersion(ctx context.Context, osFamily ftypes.OSType if osFamily == ftypes.SLES { return osver.Supported(ctx, slesEolDates, osFamily, osVer) } + if osFamily == ftypes.SLEMicro { + return osver.Supported(ctx, slemicroEolDates, osFamily, osVer) + } // tumbleweed is a rolling release, it has no version and no eol if osFamily == ftypes.OpenSUSETumbleweed { return true diff --git a/pkg/detector/ospkg/suse/suse_test.go b/pkg/detector/ospkg/suse/suse_test.go index 4db052743e82..9d480f18b0ea 100644 --- a/pkg/detector/ospkg/suse/suse_test.go +++ b/pkg/detector/ospkg/suse/suse_test.go @@ -111,6 +111,86 @@ func TestScanner_Detect(t *testing.T) { }, }, }, + { + name: "happy path: suse sle 15sp3", + fixtures: []string{ + "testdata/fixtures/suse.yaml", + "testdata/fixtures/data-source.yaml", + }, + distribution: suse.SUSEEnterpriseLinux, + args: args{ + osVer: "15.3", + pkgs: []ftypes.Package{ + { + Name: "libopenssl1_1", + Version: "1.1.1d", + Release: "150200.11.47.1", + SrcName: "libopenssl1_1", + SrcVersion: "1.1.1d", + SrcRelease: "150200.11.47.1", + Layer: ftypes.Layer{ + DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", + }, + }, + }, + }, + want: []types.DetectedVulnerability{ + { + PkgName: "libopenssl1_1", + VulnerabilityID: "SUSE-SU-2022:2251-1", + InstalledVersion: "1.1.1d-150200.11.47.1", + FixedVersion: "1.1.1d-150200.11.48.1", + Layer: ftypes.Layer{ + DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", + }, + DataSource: &dbTypes.DataSource{ + ID: vulnerability.SuseCVRF, + Name: "SUSE CVRF", + URL: "https://ftp.suse.com/pub/projects/security/cvrf/", + }, + }, + }, + }, + { + name: "happy path: suse sle micro 15.3", + fixtures: []string{ + "testdata/fixtures/suse.yaml", + "testdata/fixtures/data-source.yaml", + }, + distribution: suse.SUSEEnterpriseLinuxMicro, + args: args{ + osVer: "5.3", + pkgs: []ftypes.Package{ + { + Name: "libopenssl1_1", + Version: "1.1.1l", + Release: "150400.7.21.1", + SrcName: "libopenssl1_1", + SrcVersion: "1.1.1l", + SrcRelease: "150400.7.21.1", + Layer: ftypes.Layer{ + DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", + }, + }, + }, + }, + want: []types.DetectedVulnerability{ + { + PkgName: "libopenssl1_1", + VulnerabilityID: "SUSE-SU-2023:0311-1", + InstalledVersion: "1.1.1l-150400.7.21.1", + FixedVersion: "1.1.1l-150400.7.22.1", + Layer: ftypes.Layer{ + DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", + }, + DataSource: &dbTypes.DataSource{ + ID: vulnerability.SuseCVRF, + Name: "SUSE CVRF", + URL: "https://ftp.suse.com/pub/projects/security/cvrf/", + }, + }, + }, + }, { name: "broken bucket", fixtures: []string{ diff --git a/pkg/detector/ospkg/suse/testdata/fixtures/data-source.yaml b/pkg/detector/ospkg/suse/testdata/fixtures/data-source.yaml index b917b7e19da1..4e9ddde802d5 100644 --- a/pkg/detector/ospkg/suse/testdata/fixtures/data-source.yaml +++ b/pkg/detector/ospkg/suse/testdata/fixtures/data-source.yaml @@ -15,3 +15,8 @@ ID: "suse-cvrf" Name: "SUSE CVRF" URL: "https://ftp.suse.com/pub/projects/security/cvrf/" + - key: SUSE Linux Enterprise Micro 5.3 + value: + ID: "suse-cvrf" + Name: "SUSE CVRF" + URL: "https://ftp.suse.com/pub/projects/security/cvrf/" diff --git a/pkg/detector/ospkg/suse/testdata/fixtures/suse.yaml b/pkg/detector/ospkg/suse/testdata/fixtures/suse.yaml index 6a17594af66c..027e56673d0e 100644 --- a/pkg/detector/ospkg/suse/testdata/fixtures/suse.yaml +++ b/pkg/detector/ospkg/suse/testdata/fixtures/suse.yaml @@ -8,3 +8,23 @@ - key: CVE-2021-0001 value: FixedVersion: "" +- bucket: SUSE Linux Enterprise 15.3 + pairs: + - bucket: libopenssl1_1 + pairs: + - key: "SUSE-SU-2022:2251-1" + value: + FixedVersion: 1.1.1d-150200.11.48.1 + - bucket: openssl-1_1 + pairs: + - key: "SUSE-SU-2022:2251-1" + value: + FixedVersion: 1.1.1d-150200.11.48.1 +- bucket: SUSE Linux Enterprise Micro 5.3 + pairs: + - bucket: libopenssl1_1 + pairs: + - key: "SUSE-SU-2023:0311-1" + value: + FixedVersion: 1.1.1l-150400.7.22.1 + diff --git a/pkg/fanal/analyzer/os/release/release.go b/pkg/fanal/analyzer/os/release/release.go index 8da24644d5f7..67a18714ac1a 100644 --- a/pkg/fanal/analyzer/os/release/release.go +++ b/pkg/fanal/analyzer/os/release/release.go @@ -55,6 +55,11 @@ func (a osReleaseAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInp family = types.OpenSUSELeap case "sles": family = types.SLES + // There are various rebrands of SLE Micro, there is also one brief (and reverted rebrand) + // for SLE Micro 6.0. which was called "SL Micro 6.0" until very short before release + // and there is a "SLE Micro for Rancher" rebrand, which is used by SUSEs K8S based offerings. + case "sle-micro", "sl-micro", "sle-micro-rancher": + family = types.SLEMicro case "photon": family = types.Photon case "wolfi": diff --git a/pkg/fanal/analyzer/os/release/release_test.go b/pkg/fanal/analyzer/os/release/release_test.go index 3b534ad7b14d..532e01d9efef 100644 --- a/pkg/fanal/analyzer/os/release/release_test.go +++ b/pkg/fanal/analyzer/os/release/release_test.go @@ -70,6 +70,36 @@ func Test_osReleaseAnalyzer_Analyze(t *testing.T) { }, }, }, + { + name: "SUSE Linux Enterprise Micro", + inputFile: "testdata/slemicro", + want: &analyzer.AnalysisResult{ + OS: types.OS{ + Family: types.SLEMicro, + Name: "5.3", + }, + }, + }, + { + name: "SUSE Linux Enterprise Micro 6.0", + inputFile: "testdata/slemicro6.0", + want: &analyzer.AnalysisResult{ + OS: types.OS{ + Family: types.SLEMicro, + Name: "6.0", + }, + }, + }, + { + name: "SUSE Linux Enterprise Micro 5.4 for Rancher", + inputFile: "testdata/slemicro-rancher", + want: &analyzer.AnalysisResult{ + OS: types.OS{ + Family: types.SLEMicro, + Name: "5.4", + }, + }, + }, { name: "Photon OS", inputFile: "testdata/photon", diff --git a/pkg/fanal/analyzer/os/release/testdata/slemicro b/pkg/fanal/analyzer/os/release/testdata/slemicro new file mode 100644 index 000000000000..3e3bdaa30de5 --- /dev/null +++ b/pkg/fanal/analyzer/os/release/testdata/slemicro @@ -0,0 +1,8 @@ +NAME="SLE Micro" +VERSION="5.3" +VERSION_ID="5.3" +PRETTY_NAME="SUSE Linux Enterprise Micro 5.3" +ID="sle-micro" +ID_LIKE="suse" +ANSI_COLOR="0;32" +CPE_NAME="cpe:/o:suse:sle-micro:5.3" diff --git a/pkg/fanal/analyzer/os/release/testdata/slemicro-rancher b/pkg/fanal/analyzer/os/release/testdata/slemicro-rancher new file mode 100644 index 000000000000..83ce34662c3d --- /dev/null +++ b/pkg/fanal/analyzer/os/release/testdata/slemicro-rancher @@ -0,0 +1,13 @@ +NAME="SLE Micro" +VERSION="5.4" +VERSION_ID="5.4" +PRETTY_NAME="SUSE Linux Enterprise Micro for Rancher 5.4" +ID="sle-micro-rancher" +ID_LIKE="suse" +ANSI_COLOR="0;32" +CPE_NAME="cpe:/o:suse:sle-micro-rancher:5.4" +IMAGE_REPO="registry.suse.com/rancher/elemental-teal/5.4" +IMAGE_TAG="1.2.3-3.2.153" +IMAGE="registry.suse.com/rancher/elemental-teal/5.4:1.2.3-3.2.153" +TIMESTAMP=20240419051540 +GRUB_ENTRY_NAME="Elemental" diff --git a/pkg/fanal/analyzer/os/release/testdata/slemicro6.0 b/pkg/fanal/analyzer/os/release/testdata/slemicro6.0 new file mode 100644 index 000000000000..a18632b128a6 --- /dev/null +++ b/pkg/fanal/analyzer/os/release/testdata/slemicro6.0 @@ -0,0 +1,10 @@ +NAME="SL-Micro" +VERSION="6.0" +VERSION_ID="6.0" +PRETTY_NAME="SUSE Linux Micro 6.0" +ID="sl-micro" +ID_LIKE="suse" +ANSI_COLOR="0;32" +CPE_NAME="cpe:/o:suse:sl-micro:6.0" +HOME_URL="https://www.suse.com/products/micro/" +DOCUMENTATION_URL="https://documentation.suse.com/sl-micro/6.0/" diff --git a/pkg/fanal/test/integration/testdata/goldens/packages/opensuse-tumbleweed.json.golden b/pkg/fanal/test/integration/testdata/goldens/packages/opensuse-tumbleweed.json.golden index a651f86e3862..fa00e70aa6e6 100644 --- a/pkg/fanal/test/integration/testdata/goldens/packages/opensuse-tumbleweed.json.golden +++ b/pkg/fanal/test/integration/testdata/goldens/packages/opensuse-tumbleweed.json.golden @@ -3,7 +3,7 @@ "ID": "aaa_base@84.87+git20240523.10a5692-1.1.x86_64", "Name": "aaa_base", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/aaa_base@84.87%2Bgit20240523.10a5692-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/aaa_base@84.87%2Bgit20240523.10a5692-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "fe755017155caefc" }, "Version": "84.87+git20240523.10a5692", @@ -34,7 +34,7 @@ "ID": "bash@5.2.26-12.1.x86_64", "Name": "bash", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/bash@5.2.26-12.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/bash@5.2.26-12.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "ce56393f87add219" }, "Version": "5.2.26", @@ -61,7 +61,7 @@ "ID": "bash-sh@5.2.26-12.1.noarch", "Name": "bash-sh", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/bash-sh@5.2.26-12.1?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/bash-sh@5.2.26-12.1?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "7363186d472571e0" }, "Version": "5.2.26", @@ -87,7 +87,7 @@ "ID": "boost-license1_85_0@1.85.0-1.2.noarch", "Name": "boost-license1_85_0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/boost-license1_85_0@1.85.0-1.2?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/boost-license1_85_0@1.85.0-1.2?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "2d87c856df6862ee" }, "Version": "1.85.0", @@ -110,7 +110,7 @@ "ID": "branding-openSUSE@84.87.20240405-1.2.noarch", "Name": "branding-openSUSE", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/branding-openSUSE@84.87.20240405-1.2?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/branding-openSUSE@84.87.20240405-1.2?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "acda90b5f91cb463" }, "Version": "84.87.20240405", @@ -133,7 +133,7 @@ "ID": "ca-certificates@2+git20240415.3fe9324-1.1.noarch", "Name": "ca-certificates", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/ca-certificates@2%2Bgit20240415.3fe9324-1.1?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/ca-certificates@2%2Bgit20240415.3fe9324-1.1?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "7a18ce239fe8c044" }, "Version": "2+git20240415.3fe9324", @@ -162,7 +162,7 @@ "ID": "ca-certificates-mozilla@2.66-1.2.noarch", "Name": "ca-certificates-mozilla", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/ca-certificates-mozilla@2.66-1.2?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/ca-certificates-mozilla@2.66-1.2?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "362f343aa3c5d416" }, "Version": "2.66", @@ -189,7 +189,7 @@ "ID": "coreutils@9.5-1.1.x86_64", "Name": "coreutils", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/coreutils@9.5-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/coreutils@9.5-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "9483aa372c47866d" }, "Version": "9.5", @@ -221,7 +221,7 @@ "ID": "cracklib-dict-small@2.9.11-1.4.x86_64", "Name": "cracklib-dict-small", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/cracklib-dict-small@2.9.11-1.4?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/cracklib-dict-small@2.9.11-1.4?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "cc38aea883124e41" }, "Version": "2.9.11", @@ -244,7 +244,7 @@ "ID": "crypto-policies@20230920.570ea89-3.2.noarch", "Name": "crypto-policies", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/crypto-policies@20230920.570ea89-3.2?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/crypto-policies@20230920.570ea89-3.2?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "ebef887879b412aa" }, "Version": "20230920.570ea89", @@ -267,7 +267,7 @@ "ID": "curl@8.8.0-1.1.x86_64", "Name": "curl", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/curl@8.8.0-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/curl@8.8.0-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "50b6514bae052e62" }, "Version": "8.8.0", @@ -295,7 +295,7 @@ "ID": "file-magic@5.45-2.2.noarch", "Name": "file-magic", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/file-magic@5.45-2.2?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/file-magic@5.45-2.2?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "9318efe3deebc83a" }, "Version": "5.45", @@ -318,7 +318,7 @@ "ID": "filesystem@84.87-15.3.x86_64", "Name": "filesystem", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/filesystem@84.87-15.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/filesystem@84.87-15.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "379508af5bc6bae5" }, "Version": "84.87", @@ -344,7 +344,7 @@ "ID": "fillup@1.42-281.1.x86_64", "Name": "fillup", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/fillup@1.42-281.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/fillup@1.42-281.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "7d48bfb3846c8056" }, "Version": "1.42", @@ -370,7 +370,7 @@ "ID": "glibc@2.39-9.1.x86_64", "Name": "glibc", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/glibc@2.39-9.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/glibc@2.39-9.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "77433316d747193b" }, "Version": "2.39", @@ -396,7 +396,7 @@ "ID": "glibc-locale-base@2.39-9.1.x86_64", "Name": "glibc-locale-base", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/glibc-locale-base@2.39-9.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/glibc-locale-base@2.39-9.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "7f6f8a5c2e27af75" }, "Version": "2.39", @@ -422,7 +422,7 @@ "ID": "gpg-pubkey@29b700a4-62b07e22.", "Name": "gpg-pubkey", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/gpg-pubkey@29b700a4-62b07e22?arch=None&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/gpg-pubkey@29b700a4-62b07e22?arch=None&distro=opensuse.tumbleweed-20240607", "UID": "562934f3f56669a5" }, "Version": "29b700a4", @@ -440,7 +440,7 @@ "ID": "gpg-pubkey@39db7c82-510a966b.", "Name": "gpg-pubkey", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/gpg-pubkey@39db7c82-510a966b?arch=None&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/gpg-pubkey@39db7c82-510a966b?arch=None&distro=opensuse.tumbleweed-20240607", "UID": "5e72dadde79df0d4" }, "Version": "39db7c82", @@ -458,7 +458,7 @@ "ID": "gpg2@2.4.5-1.1.x86_64", "Name": "gpg2", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/gpg2@2.4.5-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/gpg2@2.4.5-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "e95cc1c58ec7e824" }, "Version": "2.4.5", @@ -496,7 +496,7 @@ "ID": "grep@3.11-3.1.x86_64", "Name": "grep", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/grep@3.11-3.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/grep@3.11-3.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "7c3b5ec5d53fa9f9" }, "Version": "3.11", @@ -524,7 +524,7 @@ "ID": "gzip@1.13-3.1.x86_64", "Name": "gzip", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/gzip@1.13-3.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/gzip@1.13-3.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "f51af60e831e41e" }, "Version": "1.13", @@ -551,7 +551,7 @@ "ID": "krb5@1.21.2-5.1.x86_64", "Name": "krb5", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/krb5@1.21.2-5.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/krb5@1.21.2-5.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "f22a7694d8a232ac" }, "Version": "1.21.2", @@ -583,7 +583,7 @@ "ID": "libabsl_lite_2401_0_0@20240116.2-2.1.x86_64", "Name": "libabsl_lite_2401_0_0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libabsl_lite_2401_0_0@20240116.2-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libabsl_lite_2401_0_0@20240116.2-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "24307f175234d50" }, "Version": "20240116.2", @@ -611,7 +611,7 @@ "ID": "libacl1@2.3.2-2.1.x86_64", "Name": "libacl1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libacl1@2.3.2-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libacl1@2.3.2-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "6e55e249889869ed" }, "Version": "2.3.2", @@ -637,7 +637,7 @@ "ID": "libassuan0@2.5.7-1.1.x86_64", "Name": "libassuan0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libassuan0@2.5.7-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libassuan0@2.5.7-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "4a9f149fc3b4d802" }, "Version": "2.5.7", @@ -664,7 +664,7 @@ "ID": "libattr1@2.5.2-1.2.x86_64", "Name": "libattr1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libattr1@2.5.2-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libattr1@2.5.2-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "bf6e596e053cc667" }, "Version": "2.5.2", @@ -690,7 +690,7 @@ "ID": "libaudit1@3.1.1-1.6.x86_64", "Name": "libaudit1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libaudit1@3.1.1-1.6?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libaudit1@3.1.1-1.6?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "c2ab09cc3b09bf56" }, "Version": "3.1.1", @@ -716,7 +716,7 @@ "ID": "libaugeas0@1.14.1-1.3.x86_64", "Name": "libaugeas0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libaugeas0@1.14.1-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libaugeas0@1.14.1-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "bc9b541f623eec37" }, "Version": "1.14.1", @@ -744,7 +744,7 @@ "ID": "libblkid1@2.40.1-2.1.x86_64", "Name": "libblkid1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libblkid1@2.40.1-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libblkid1@2.40.1-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "bcf4491906d1eb4d" }, "Version": "2.40.1", @@ -771,7 +771,7 @@ "ID": "libboost_thread1_85_0@1.85.0-1.2.x86_64", "Name": "libboost_thread1_85_0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libboost_thread1_85_0@1.85.0-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libboost_thread1_85_0@1.85.0-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "b8612fd1d8aa51a7" }, "Version": "1.85.0", @@ -800,7 +800,7 @@ "ID": "libbrotlicommon1@1.1.0-1.3.x86_64", "Name": "libbrotlicommon1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libbrotlicommon1@1.1.0-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libbrotlicommon1@1.1.0-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "f1d7b84b18abde08" }, "Version": "1.1.0", @@ -826,7 +826,7 @@ "ID": "libbrotlidec1@1.1.0-1.3.x86_64", "Name": "libbrotlidec1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libbrotlidec1@1.1.0-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libbrotlidec1@1.1.0-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "5c297a82e6701a0d" }, "Version": "1.1.0", @@ -853,7 +853,7 @@ "ID": "libbz2-1@1.0.8-5.10.x86_64", "Name": "libbz2-1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libbz2-1@1.0.8-5.10?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libbz2-1@1.0.8-5.10?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "702f3dd378cba8f0" }, "Version": "1.0.8", @@ -879,7 +879,7 @@ "ID": "libcap-ng0@0.8.5-1.1.x86_64", "Name": "libcap-ng0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libcap-ng0@0.8.5-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libcap-ng0@0.8.5-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "b40d6fdd09912405" }, "Version": "0.8.5", @@ -905,7 +905,7 @@ "ID": "libcap2@2.70-1.1.x86_64", "Name": "libcap2", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libcap2@2.70-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libcap2@2.70-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "c33018bbf8c4bdfa" }, "Version": "2.70", @@ -931,7 +931,7 @@ "ID": "libcom_err2@1.47.0-4.2.x86_64", "Name": "libcom_err2", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libcom_err2@1.47.0-4.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libcom_err2@1.47.0-4.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "58b023020895cfea" }, "Version": "1.47.0", @@ -957,7 +957,7 @@ "ID": "libcrypt1@4.4.36-1.6.x86_64", "Name": "libcrypt1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libcrypt1@4.4.36-1.6?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libcrypt1@4.4.36-1.6?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "541be9a801034440" }, "Version": "4.4.36", @@ -983,7 +983,7 @@ "ID": "libcurl4@8.8.0-1.1.x86_64", "Name": "libcurl4", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libcurl4@8.8.0-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libcurl4@8.8.0-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "59c3c7a8962c110a" }, "Version": "8.8.0", @@ -1019,7 +1019,7 @@ "ID": "libeconf0@0.6.3-1.1.x86_64", "Name": "libeconf0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libeconf0@0.6.3-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libeconf0@0.6.3-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "9e3e97464bc6164b" }, "Version": "0.6.3", @@ -1045,7 +1045,7 @@ "ID": "libfa1@1.14.1-1.3.x86_64", "Name": "libfa1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libfa1@1.14.1-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libfa1@1.14.1-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "9df420b84b79a62" }, "Version": "1.14.1", @@ -1071,7 +1071,7 @@ "ID": "libfdisk1@2.40.1-2.1.x86_64", "Name": "libfdisk1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libfdisk1@2.40.1-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libfdisk1@2.40.1-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "ab47b44e7c45eab1" }, "Version": "2.40.1", @@ -1099,7 +1099,7 @@ "ID": "libffi8@3.4.6-1.1.x86_64", "Name": "libffi8", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libffi8@3.4.6-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libffi8@3.4.6-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "a569681a5276bde6" }, "Version": "3.4.6", @@ -1125,7 +1125,7 @@ "ID": "libgcc_s1@14.1.0+git10173-1.1.x86_64", "Name": "libgcc_s1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libgcc_s1@14.1.0%2Bgit10173-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libgcc_s1@14.1.0%2Bgit10173-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "3130b825fbc3a81e" }, "Version": "14.1.0+git10173", @@ -1151,7 +1151,7 @@ "ID": "libgcrypt20@1.10.3-3.3.x86_64", "Name": "libgcrypt20", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libgcrypt20@1.10.3-3.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libgcrypt20@1.10.3-3.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "ac38e6e75132d1c6" }, "Version": "1.10.3", @@ -1178,7 +1178,7 @@ "ID": "libglib-2_0-0@2.80.2-1.1.x86_64", "Name": "libglib-2_0-0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libglib-2_0-0@2.80.2-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libglib-2_0-0@2.80.2-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "e3dccc27a6f44a3d" }, "Version": "2.80.2", @@ -1205,7 +1205,7 @@ "ID": "libgmp10@6.3.0-3.2.x86_64", "Name": "libgmp10", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libgmp10@6.3.0-3.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libgmp10@6.3.0-3.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "fb3994e26d59ae4f" }, "Version": "6.3.0", @@ -1231,7 +1231,7 @@ "ID": "libgpg-error0@1.49-1.1.x86_64", "Name": "libgpg-error0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libgpg-error0@1.49-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libgpg-error0@1.49-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "a3b16ea69b05fe60" }, "Version": "1.49", @@ -1257,7 +1257,7 @@ "ID": "libgpgme11@1.23.2-4.2.x86_64", "Name": "libgpgme11", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libgpgme11@1.23.2-4.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libgpgme11@1.23.2-4.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "6d9271ab523fb009" }, "Version": "1.23.2", @@ -1286,7 +1286,7 @@ "ID": "libidn2-0@2.3.7-1.2.x86_64", "Name": "libidn2-0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libidn2-0@2.3.7-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libidn2-0@2.3.7-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "ae81c3e9fc0d0fc3" }, "Version": "2.3.7", @@ -1313,7 +1313,7 @@ "ID": "libkeyutils1@1.6.3-7.2.x86_64", "Name": "libkeyutils1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libkeyutils1@1.6.3-7.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libkeyutils1@1.6.3-7.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "f9f931edfe4b540c" }, "Version": "1.6.3", @@ -1339,7 +1339,7 @@ "ID": "libksba8@1.6.6-1.1.x86_64", "Name": "libksba8", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libksba8@1.6.6-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libksba8@1.6.6-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "c532eef98bb36938" }, "Version": "1.6.6", @@ -1366,7 +1366,7 @@ "ID": "libldap2@2.6.7-2.1.x86_64", "Name": "libldap2", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libldap2@2.6.7-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libldap2@2.6.7-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "55fa8e45be9ed78" }, "Version": "2.6.7", @@ -1394,7 +1394,7 @@ "ID": "liblua5_4-5@5.4.6-3.3.x86_64", "Name": "liblua5_4-5", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/liblua5_4-5@5.4.6-3.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/liblua5_4-5@5.4.6-3.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "98b4001b2f59f46" }, "Version": "5.4.6", @@ -1420,7 +1420,7 @@ "ID": "liblz4-1@1.9.4-2.8.x86_64", "Name": "liblz4-1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/liblz4-1@1.9.4-2.8?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/liblz4-1@1.9.4-2.8?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "267a6bfb140f0d45" }, "Version": "1.9.4", @@ -1446,7 +1446,7 @@ "ID": "liblzma5@5.6.2-1.1.x86_64", "Name": "liblzma5", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/liblzma5@5.6.2-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/liblzma5@5.6.2-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "304510f1f6669e2c" }, "Version": "5.6.2", @@ -1472,7 +1472,7 @@ "ID": "libmagic1@5.45-2.2.x86_64", "Name": "libmagic1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libmagic1@5.45-2.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libmagic1@5.45-2.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "d8fdc2934df34a83" }, "Version": "5.45", @@ -1503,7 +1503,7 @@ "ID": "libmount1@2.40.1-2.1.x86_64", "Name": "libmount1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libmount1@2.40.1-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libmount1@2.40.1-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "8386ec24a06557ea" }, "Version": "2.40.1", @@ -1531,7 +1531,7 @@ "ID": "libncurses6@6.5.20240601-38.1.x86_64", "Name": "libncurses6", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libncurses6@6.5.20240601-38.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libncurses6@6.5.20240601-38.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "9513bf16199cee6b" }, "Version": "6.5.20240601", @@ -1560,7 +1560,7 @@ "ID": "libnghttp2-14@1.61.0-1.1.x86_64", "Name": "libnghttp2-14", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libnghttp2-14@1.61.0-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libnghttp2-14@1.61.0-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "de28696676fc1ebd" }, "Version": "1.61.0", @@ -1586,7 +1586,7 @@ "ID": "libnpth0@1.7-1.1.x86_64", "Name": "libnpth0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libnpth0@1.7-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libnpth0@1.7-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "7bff27e583fb62b3" }, "Version": "1.7", @@ -1612,7 +1612,7 @@ "ID": "libnss_usrfiles2@2.27.1-1.2.x86_64", "Name": "libnss_usrfiles2", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libnss_usrfiles2@2.27.1-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libnss_usrfiles2@2.27.1-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "d3c8c8f840c86b12" }, "Version": "2.27.1", @@ -1638,7 +1638,7 @@ "ID": "libopenssl-3-fips-provider@3.1.4-9.1.x86_64", "Name": "libopenssl-3-fips-provider", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libopenssl-3-fips-provider@3.1.4-9.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libopenssl-3-fips-provider@3.1.4-9.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "65c56c2870042412" }, "Version": "3.1.4", @@ -1665,7 +1665,7 @@ "ID": "libopenssl3@3.1.4-9.1.x86_64", "Name": "libopenssl3", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libopenssl3@3.1.4-9.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libopenssl3@3.1.4-9.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "f051425f385d2b99" }, "Version": "3.1.4", @@ -1693,7 +1693,7 @@ "ID": "libp11-kit0@0.25.3-1.3.x86_64", "Name": "libp11-kit0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libp11-kit0@0.25.3-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libp11-kit0@0.25.3-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "fbca9a69218ce8e7" }, "Version": "0.25.3", @@ -1720,7 +1720,7 @@ "ID": "libpcre2-8-0@10.43-3.1.x86_64", "Name": "libpcre2-8-0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libpcre2-8-0@10.43-3.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libpcre2-8-0@10.43-3.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "dabdfbc56d214ae6" }, "Version": "10.43", @@ -1746,7 +1746,7 @@ "ID": "libpopt0@1.19-1.8.x86_64", "Name": "libpopt0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libpopt0@1.19-1.8?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libpopt0@1.19-1.8?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "98fa32fcd9ee1e39" }, "Version": "1.19", @@ -1772,7 +1772,7 @@ "ID": "libprocps8@3.3.17-17.1.x86_64", "Name": "libprocps8", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libprocps8@3.3.17-17.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libprocps8@3.3.17-17.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "f874f4997e1438be" }, "Version": "3.3.17", @@ -1799,7 +1799,7 @@ "ID": "libprotobuf-lite25_3_0@25.3-11.2.x86_64", "Name": "libprotobuf-lite25_3_0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libprotobuf-lite25_3_0@25.3-11.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libprotobuf-lite25_3_0@25.3-11.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "b306bfd6494e6405" }, "Version": "25.3", @@ -1828,7 +1828,7 @@ "ID": "libpsl5@0.21.5-1.2.x86_64", "Name": "libpsl5", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libpsl5@0.21.5-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libpsl5@0.21.5-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "5d2411f7ede68692" }, "Version": "0.21.5", @@ -1856,7 +1856,7 @@ "ID": "libreadline8@8.2.10-1.3.x86_64", "Name": "libreadline8", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libreadline8@8.2.10-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libreadline8@8.2.10-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "9271e2cd0119054c" }, "Version": "8.2.10", @@ -1883,7 +1883,7 @@ "ID": "libsasl2-3@2.1.28-8.1.x86_64", "Name": "libsasl2-3", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libsasl2-3@2.1.28-8.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libsasl2-3@2.1.28-8.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "fe2536ad8601f334" }, "Version": "2.1.28", @@ -1909,7 +1909,7 @@ "ID": "libselinux1@3.6-1.3.x86_64", "Name": "libselinux1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libselinux1@3.6-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libselinux1@3.6-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "6bc8fe60a073ba96" }, "Version": "3.6", @@ -1936,7 +1936,7 @@ "ID": "libsemanage-conf@3.6-2.1.x86_64", "Name": "libsemanage-conf", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libsemanage-conf@3.6-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libsemanage-conf@3.6-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "56c91988ca2e8ce5" }, "Version": "3.6", @@ -1959,7 +1959,7 @@ "ID": "libsemanage2@3.6-2.1.x86_64", "Name": "libsemanage2", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libsemanage2@3.6-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libsemanage2@3.6-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "d945b0271ed45cf5" }, "Version": "3.6", @@ -1990,7 +1990,7 @@ "ID": "libsepol2@3.6-1.3.x86_64", "Name": "libsepol2", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libsepol2@3.6-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libsepol2@3.6-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "f2aaf81754d3169d" }, "Version": "3.6", @@ -2016,7 +2016,7 @@ "ID": "libsigc-2_0-0@2.12.1-2.3.x86_64", "Name": "libsigc-2_0-0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libsigc-2_0-0@2.12.1-2.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libsigc-2_0-0@2.12.1-2.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "c4d52d6f33dee391" }, "Version": "2.12.1", @@ -2044,7 +2044,7 @@ "ID": "libsmartcols1@2.40.1-2.1.x86_64", "Name": "libsmartcols1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libsmartcols1@2.40.1-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libsmartcols1@2.40.1-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "5302abe63411170d" }, "Version": "2.40.1", @@ -2070,7 +2070,7 @@ "ID": "libsolv-tools-base@0.7.29-1.1.x86_64", "Name": "libsolv-tools-base", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libsolv-tools-base@0.7.29-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libsolv-tools-base@0.7.29-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "f2adb3efc201c696" }, "Version": "0.7.29", @@ -2102,7 +2102,7 @@ "ID": "libsqlite3-0@3.46.0-1.1.x86_64", "Name": "libsqlite3-0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libsqlite3-0@3.46.0-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libsqlite3-0@3.46.0-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "d9bf1a49d16f0c" }, "Version": "3.46.0", @@ -2128,7 +2128,7 @@ "ID": "libssh-config@0.10.6-2.1.x86_64", "Name": "libssh-config", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libssh-config@0.10.6-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libssh-config@0.10.6-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "8628d51e34c2f5b1" }, "Version": "0.10.6", @@ -2151,7 +2151,7 @@ "ID": "libssh4@0.10.6-2.1.x86_64", "Name": "libssh4", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libssh4@0.10.6-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libssh4@0.10.6-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "d07880785aee16c8" }, "Version": "0.10.6", @@ -2181,7 +2181,7 @@ "ID": "libstdc++6@14.1.0+git10173-1.1.x86_64", "Name": "libstdc++6", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libstdc%2B%2B6@14.1.0%2Bgit10173-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libstdc%2B%2B6@14.1.0%2Bgit10173-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "f3345c3d3261e7e9" }, "Version": "14.1.0+git10173", @@ -2208,7 +2208,7 @@ "ID": "libsubid4@4.15.1-1.2.x86_64", "Name": "libsubid4", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libsubid4@4.15.1-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libsubid4@4.15.1-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "e155b313aa6da812" }, "Version": "4.15.1", @@ -2236,7 +2236,7 @@ "ID": "libsystemd0@255.7-2.1.x86_64", "Name": "libsystemd0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libsystemd0@255.7-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libsystemd0@255.7-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "4fa3c2608f054287" }, "Version": "255.7", @@ -2267,7 +2267,7 @@ "ID": "libtasn1-6@4.19.0-1.7.x86_64", "Name": "libtasn1-6", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libtasn1-6@4.19.0-1.7?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libtasn1-6@4.19.0-1.7?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "35e287fcdf033bd1" }, "Version": "4.19.0", @@ -2293,7 +2293,7 @@ "ID": "libudev1@255.7-2.1.x86_64", "Name": "libudev1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libudev1@255.7-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libudev1@255.7-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "4ae1c62105f1f901" }, "Version": "255.7", @@ -2320,7 +2320,7 @@ "ID": "libunistring5@1.2-1.1.x86_64", "Name": "libunistring5", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libunistring5@1.2-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libunistring5@1.2-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "e8be56f8ad59a760" }, "Version": "1.2", @@ -2346,7 +2346,7 @@ "ID": "libusb-1_0-0@1.0.27-1.2.x86_64", "Name": "libusb-1_0-0", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libusb-1_0-0@1.0.27-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libusb-1_0-0@1.0.27-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "dab90c8d517b4ee4" }, "Version": "1.0.27", @@ -2373,7 +2373,7 @@ "ID": "libuuid1@2.40.1-2.1.x86_64", "Name": "libuuid1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libuuid1@2.40.1-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libuuid1@2.40.1-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "bc5c46e1650d4a95" }, "Version": "2.40.1", @@ -2399,7 +2399,7 @@ "ID": "libverto1@0.3.2-3.3.x86_64", "Name": "libverto1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libverto1@0.3.2-3.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libverto1@0.3.2-3.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "8c13b7ac8ed99616" }, "Version": "0.3.2", @@ -2425,7 +2425,7 @@ "ID": "libxml2-2@2.12.7-1.1.x86_64", "Name": "libxml2-2", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libxml2-2@2.12.7-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libxml2-2@2.12.7-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "1285499ab636c5d9" }, "Version": "2.12.7", @@ -2453,7 +2453,7 @@ "ID": "libyaml-cpp0_8@0.8.0-1.3.x86_64", "Name": "libyaml-cpp0_8", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libyaml-cpp0_8@0.8.0-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libyaml-cpp0_8@0.8.0-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "d743795a2d65f87b" }, "Version": "0.8.0", @@ -2481,7 +2481,7 @@ "ID": "libz1@1.3.1-1.1.x86_64", "Name": "libz1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libz1@1.3.1-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libz1@1.3.1-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "f09857fffac622a" }, "Version": "1.3.1", @@ -2507,7 +2507,7 @@ "ID": "libzck1@1.4.0-2.1.x86_64", "Name": "libzck1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libzck1@1.4.0-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libzck1@1.4.0-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "76b3d8e58402a974" }, "Version": "1.4.0", @@ -2535,7 +2535,7 @@ "ID": "libzstd1@1.5.6-1.1.x86_64", "Name": "libzstd1", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libzstd1@1.5.6-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libzstd1@1.5.6-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "4edc1117cd2019eb" }, "Version": "1.5.6", @@ -2561,7 +2561,7 @@ "ID": "libzypp@17.34.1-1.1.x86_64", "Name": "libzypp", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/libzypp@17.34.1-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/libzypp@17.34.1-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "3545239e91f3bd9" }, "Version": "17.34.1", @@ -2606,7 +2606,7 @@ "ID": "login_defs@4.15.1-1.2.noarch", "Name": "login_defs", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/login_defs@4.15.1-1.2?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/login_defs@4.15.1-1.2?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "1695371f9551a301" }, "Version": "4.15.1", @@ -2632,7 +2632,7 @@ "ID": "lsb-release@3.3-1.3.noarch", "Name": "lsb-release", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/lsb-release@3.3-1.3?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/lsb-release@3.3-1.3?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "8c82a3a248c52a13" }, "Version": "3.3", @@ -2659,7 +2659,7 @@ "ID": "ncurses-utils@6.5.20240601-38.1.x86_64", "Name": "ncurses-utils", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/ncurses-utils@6.5.20240601-38.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/ncurses-utils@6.5.20240601-38.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "90d23a67ceb37784" }, "Version": "6.5.20240601", @@ -2686,7 +2686,7 @@ "ID": "netcfg@11.6-13.3.noarch", "Name": "netcfg", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/netcfg@11.6-13.3?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/netcfg@11.6-13.3?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "c32526003d9c5528" }, "Version": "11.6", @@ -2712,7 +2712,7 @@ "ID": "openSUSE-build-key@1.0-53.1.x86_64", "Name": "openSUSE-build-key", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/openSUSE-build-key@1.0-53.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/openSUSE-build-key@1.0-53.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "ed8309d0e84993e4" }, "Version": "1.0", @@ -2739,7 +2739,7 @@ "ID": "openSUSE-release@20240607-2943.1.x86_64", "Name": "openSUSE-release", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/openSUSE-release@20240607-2943.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/openSUSE-release@20240607-2943.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "ad908712f8c8e5ab" }, "Version": "20240607", @@ -2766,7 +2766,7 @@ "ID": "openSUSE-release-appliance-docker@20240607-2943.1.x86_64", "Name": "openSUSE-release-appliance-docker", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/openSUSE-release-appliance-docker@20240607-2943.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/openSUSE-release-appliance-docker@20240607-2943.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "46f06026407817a0" }, "Version": "20240607", @@ -2789,7 +2789,7 @@ "ID": "openssl@3.1.4-3.2.noarch", "Name": "openssl", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/openssl@3.1.4-3.2?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/openssl@3.1.4-3.2?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "cd2ead77021cf857" }, "Version": "3.1.4", @@ -2815,7 +2815,7 @@ "ID": "openssl-3@3.1.4-9.1.x86_64", "Name": "openssl-3", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/openssl-3@3.1.4-9.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/openssl-3@3.1.4-9.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "da148866e5ba5d92" }, "Version": "3.1.4", @@ -2846,7 +2846,7 @@ "ID": "p11-kit@0.25.3-1.3.x86_64", "Name": "p11-kit", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/p11-kit@0.25.3-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/p11-kit@0.25.3-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "7da38dbf3cd84149" }, "Version": "0.25.3", @@ -2874,7 +2874,7 @@ "ID": "p11-kit-tools@0.25.3-1.3.x86_64", "Name": "p11-kit-tools", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/p11-kit-tools@0.25.3-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/p11-kit-tools@0.25.3-1.3?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "fb534863cc7b3050" }, "Version": "0.25.3", @@ -2902,7 +2902,7 @@ "ID": "pam@1.6.1-1.1.x86_64", "Name": "pam", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/pam@1.6.1-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/pam@1.6.1-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "2cc82a7c85091dc0" }, "Version": "1.6.1", @@ -2935,7 +2935,7 @@ "ID": "patterns-base-fips@20200505-51.1.x86_64", "Name": "patterns-base-fips", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/patterns-base-fips@20200505-51.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/patterns-base-fips@20200505-51.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "70a74594ade38509" }, "Version": "20200505", @@ -2958,7 +2958,7 @@ "ID": "patterns-base-minimal_base@20200505-51.1.x86_64", "Name": "patterns-base-minimal_base", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/patterns-base-minimal_base@20200505-51.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/patterns-base-minimal_base@20200505-51.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "22550c4b68de6581" }, "Version": "20200505", @@ -2987,7 +2987,7 @@ "ID": "permctl@1699_20240522-1.1.x86_64", "Name": "permctl", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/permctl@1699_20240522-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/permctl@1699_20240522-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "cfcd9931dafbea39" }, "Version": "1699_20240522", @@ -3016,7 +3016,7 @@ "ID": "permissions@1699_20240522-1.1.x86_64", "Name": "permissions", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/permissions@1699_20240522-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/permissions@1699_20240522-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "971d93fae8da6b23" }, "Version": "1699_20240522", @@ -3043,7 +3043,7 @@ "ID": "permissions-config@1699_20240522-1.1.noarch", "Name": "permissions-config", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/permissions-config@1699_20240522-1.1?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/permissions-config@1699_20240522-1.1?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "8bd3994be34b3e73" }, "Version": "1699_20240522", @@ -3072,7 +3072,7 @@ "ID": "pinentry@1.2.1-3.5.x86_64", "Name": "pinentry", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/pinentry@1.2.1-3.5?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/pinentry@1.2.1-3.5?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "90686edea2822ef8" }, "Version": "1.2.1", @@ -3102,7 +3102,7 @@ "ID": "procps@3.3.17-17.1.x86_64", "Name": "procps", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/procps@3.3.17-17.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/procps@3.3.17-17.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "41a25e357a85fe17" }, "Version": "3.3.17", @@ -3131,7 +3131,7 @@ "ID": "rpm@4.19.1.1-3.2.x86_64", "Name": "rpm", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/rpm@4.19.1.1-3.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/rpm@4.19.1.1-3.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "6385ed7e7827135a" }, "Version": "4.19.1.1", @@ -3170,7 +3170,7 @@ "ID": "rpm-config-SUSE@20240214-1.2.noarch", "Name": "rpm-config-SUSE", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/rpm-config-SUSE@20240214-1.2?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/rpm-config-SUSE@20240214-1.2?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "b0a53b3b9cd8de6e" }, "Version": "20240214", @@ -3198,7 +3198,7 @@ "ID": "sed@4.9-2.6.x86_64", "Name": "sed", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/sed@4.9-2.6?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/sed@4.9-2.6?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "465c6c9c97824acd" }, "Version": "4.9", @@ -3226,7 +3226,7 @@ "ID": "shadow@4.15.1-1.2.x86_64", "Name": "shadow", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/shadow@4.15.1-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/shadow@4.15.1-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "7fefaa914168ef4f" }, "Version": "4.15.1", @@ -3265,7 +3265,7 @@ "ID": "system-user-root@20190513-2.16.noarch", "Name": "system-user-root", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/system-user-root@20190513-2.16?arch=noarch&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/system-user-root@20190513-2.16?arch=noarch&distro=opensuse.tumbleweed-20240607", "UID": "cc450033801f0db5" }, "Version": "20190513", @@ -3288,7 +3288,7 @@ "ID": "tar@1.35-2.2.x86_64", "Name": "tar", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/tar@1.35-2.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/tar@1.35-2.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "6f7d60b91f9b815f" }, "Version": "1.35", @@ -3316,7 +3316,7 @@ "ID": "terminfo-base@6.5.20240601-38.1.x86_64", "Name": "terminfo-base", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/terminfo-base@6.5.20240601-38.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/terminfo-base@6.5.20240601-38.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "ba53240ca965e6c0" }, "Version": "6.5.20240601", @@ -3342,7 +3342,7 @@ "ID": "timezone@2024a-3.2.x86_64", "Name": "timezone", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/timezone@2024a-3.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/timezone@2024a-3.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "aa7fc225c615b895" }, "Version": "2024a", @@ -3369,7 +3369,7 @@ "ID": "util-linux@2.40.1-2.1.x86_64", "Name": "util-linux", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/util-linux@2.40.1-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/util-linux@2.40.1-2.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "1440e3eb3dfc6c5" }, "Version": "2.40.1", @@ -3412,7 +3412,7 @@ "ID": "xz@5.6.2-1.1.x86_64", "Name": "xz", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/xz@5.6.2-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/xz@5.6.2-1.1?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "1c46963e750a4a9" }, "Version": "5.6.2", @@ -3440,7 +3440,7 @@ "ID": "zypper@1.14.73-1.2.x86_64", "Name": "zypper", "Identifier": { - "PURL": "pkg:rpm/opensuse.tumbleweed/zypper@1.14.73-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", + "PURL": "pkg:rpm/opensuse/zypper@1.14.73-1.2?arch=x86_64&distro=opensuse.tumbleweed-20240607", "UID": "9d7cafcab0f1fed2" }, "Version": "1.14.73", diff --git a/pkg/fanal/types/const.go b/pkg/fanal/types/const.go index ffe1e0718764..c304f40bac5f 100644 --- a/pkg/fanal/types/const.go +++ b/pkg/fanal/types/const.go @@ -37,6 +37,7 @@ const ( Photon OSType = "photon" RedHat OSType = "redhat" Rocky OSType = "rocky" + SLEMicro OSType = "suse linux enterprise micro" SLES OSType = "suse linux enterprise server" Ubuntu OSType = "ubuntu" Wolfi OSType = "wolfi" diff --git a/pkg/purl/purl.go b/pkg/purl/purl.go index d9bff7b11e15..a7b1cb9181f0 100644 --- a/pkg/purl/purl.go +++ b/pkg/purl/purl.go @@ -358,16 +358,19 @@ func parseRPM(fos *ftypes.OS, modularityLabel string) (ftypes.OSType, packageurl return "", packageurl.Qualifiers{} } - // SLES string has whitespace family := fos.Family - if fos.Family == ftypes.SLES { - family = "sles" + // SLES string has whitespace, also highlevel family is not the same as distro + if fos.Family == ftypes.SLES || fos.Family == ftypes.SLEMicro { + family = "suse" + } + if fos.Family == ftypes.OpenSUSETumbleweed || fos.Family == ftypes.OpenSUSELeap { + family = "opensuse" } qualifiers := packageurl.Qualifiers{ { Key: "distro", - Value: fmt.Sprintf("%s-%s", family, fos.Name), + Value: fmt.Sprintf("%s-%s", fos.Family, fos.Name), }, } @@ -476,7 +479,7 @@ func purlType(t ftypes.TargetType) string { return packageurl.TypeDebian case ftypes.RedHat, ftypes.CentOS, ftypes.Rocky, ftypes.Alma, ftypes.Amazon, ftypes.Fedora, ftypes.Oracle, ftypes.OpenSUSE, - ftypes.OpenSUSELeap, ftypes.OpenSUSETumbleweed, ftypes.SLES, ftypes.Photon, + ftypes.OpenSUSELeap, ftypes.OpenSUSETumbleweed, ftypes.SLES, ftypes.SLEMicro, ftypes.Photon, ftypes.Azure, ftypes.CBLMariner: return packageurl.TypeRPM case TypeOCI: From de40df9408d6d856a3ad384ec9f086edce3aa382 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Mon, 30 Sep 2024 10:50:53 +0600 Subject: [PATCH 18/94] fix(misconf): disable DS016 check for image history analyzer (#7540) Signed-off-by: nikpivkin --- .../analyzer/imgconf/dockerfile/dockerfile.go | 5 +++ .../imgconf/dockerfile/dockerfile_test.go | 41 +++++++++++++++++++ pkg/misconf/scanner.go | 3 ++ 3 files changed, 49 insertions(+) diff --git a/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go b/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go index 5a974a8dd1d1..c79a81f54c61 100644 --- a/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go +++ b/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go @@ -16,6 +16,10 @@ import ( "github.com/aquasecurity/trivy/pkg/misconf" ) +var disabledChecks = []string{ + "DS016", // See https://github.com/aquasecurity/trivy/issues/7368 +} + const analyzerVersion = 1 func init() { @@ -27,6 +31,7 @@ type historyAnalyzer struct { } func newHistoryAnalyzer(opts analyzer.ConfigAnalyzerOptions) (analyzer.ConfigAnalyzer, error) { + opts.MisconfScannerOption.DisabledCheckIDs = append(opts.MisconfScannerOption.DisabledCheckIDs, disabledChecks...) s, err := misconf.NewScanner(detection.FileTypeDockerfile, opts.MisconfScannerOption) if err != nil { return nil, xerrors.Errorf("misconfiguration scanner error: %w", err) diff --git a/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile_test.go b/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile_test.go index 1ee81016ac8c..c454de8ba3d4 100644 --- a/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile_test.go +++ b/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile_test.go @@ -284,6 +284,47 @@ func Test_historyAnalyzer_Analyze(t *testing.T) { Config: nil, }, }, + { + name: "DS016 check not detected", + input: analyzer.ConfigAnalysisInput{ + Config: &v1.ConfigFile{ + Config: v1.Config{ + Healthcheck: &v1.HealthConfig{ + Test: []string{"CMD-SHELL", "curl --fail http://localhost:3000 || exit 1"}, + Interval: time.Second * 10, + Timeout: time.Second * 3, + }, + }, + History: []v1.History{ + { + // duplicate command from another layer + CreatedBy: `/bin/sh -c #(nop) CMD [\"/bin/bash\"]`, + EmptyLayer: true, + }, + { + CreatedBy: "/bin/sh -c #(nop) ADD file:e4d600fc4c9c293efe360be7b30ee96579925d1b4634c94332e2ec73f7d8eca1 in /", + }, + { + CreatedBy: `HEALTHCHECK &{["CMD-SHELL" "curl --fail http://localhost:3000 || exit 1"] "10s" "3s" "0s" '\x00'}`, + }, + { + CreatedBy: `USER user`, + EmptyLayer: true, + }, + { + CreatedBy: `/bin/sh -c #(nop) CMD [\"/bin/sh\"]`, + EmptyLayer: true, + }, + }, + }, + }, + want: &analyzer.ConfigAnalysisResult{ + Misconfiguration: &types.Misconfiguration{ + FileType: types.Dockerfile, + FilePath: "Dockerfile", + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/misconf/scanner.go b/pkg/misconf/scanner.go index db203364a3e4..78f4f4bdb158 100644 --- a/pkg/misconf/scanner.go +++ b/pkg/misconf/scanner.go @@ -74,6 +74,8 @@ type ScannerOption struct { FilePatterns []string ConfigFileSchemas []*ConfigFileSchema + + DisabledCheckIDs []string } func (o *ScannerOption) Sort() { @@ -212,6 +214,7 @@ func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerO rego.WithEmbeddedPolicies(!opt.DisableEmbeddedPolicies), rego.WithEmbeddedLibraries(!opt.DisableEmbeddedLibraries), options.ScannerWithIncludeDeprecatedChecks(opt.IncludeDeprecatedChecks), + rego.WithDisabledCheckIDs(opt.DisabledCheckIDs...), } policyFS, policyPaths, err := CreatePolicyFS(opt.PolicyPaths) From cb16d43b696284e7256adc4fff1ff108d1c7bff3 Mon Sep 17 00:00:00 2001 From: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Date: Mon, 30 Sep 2024 16:42:12 +0600 Subject: [PATCH 19/94] ci: split `save` and `restore` cache actions (#7614) --- .github/workflows/cache-test-images.yaml | 84 ++++++++++++++++++++++++ .github/workflows/test.yaml | 9 +-- 2 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/cache-test-images.yaml diff --git a/.github/workflows/cache-test-images.yaml b/.github/workflows/cache-test-images.yaml new file mode 100644 index 000000000000..da8aff10cfd2 --- /dev/null +++ b/.github/workflows/cache-test-images.yaml @@ -0,0 +1,84 @@ +name: Cache test images +on: + schedule: + - cron: "0 0 * * *" # Run this workflow every day at 00:00 to avoid cache deletion. + workflow_dispatch: + +jobs: + test-images: + name: Cache test images + runs-on: ubuntu-latest + steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v4.1.6 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Install tools + uses: aquaproj/aqua-installer@v3.0.1 + with: + aqua_version: v1.25.0 + + - name: Generate image list digest + if: github.ref_name == 'main' + id: image-digest + run: | + IMAGE_LIST=$(skopeo list-tags docker://ghcr.io/aquasecurity/trivy-test-images) + DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) + echo "digest=$DIGEST" >> $GITHUB_OUTPUT + + ## We need to work with test image cache only for main branch + - name: Restore and save test images cache + if: github.ref_name == 'main' + uses: actions/cache@v4 + with: + path: integration/testdata/fixtures/images + key: cache-test-images-${{ steps.image-digest.outputs.digest }} + restore-keys: + cache-test-images- + + - name: Download test images + if: github.ref_name == 'main' + run: mage test:fixtureContainerImages + + test-vm-images: + name: Cache test VM images + runs-on: ubuntu-latest + steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v4.1.6 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Install tools + uses: aquaproj/aqua-installer@v3.0.1 + with: + aqua_version: v1.25.0 + + - name: Generate image list digest + if: github.ref_name == 'main' + id: image-digest + run: | + IMAGE_LIST=$(skopeo list-tags docker://ghcr.io/aquasecurity/trivy-test-vm-images) + DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) + echo "digest=$DIGEST" >> $GITHUB_OUTPUT + + ## We need to work with test VM image cache only for main branch + - name: Restore and save test VM images cache + if: github.ref_name == 'main' + uses: actions/cache@v4 + with: + path: integration/testdata/fixtures/vm-images + key: cache-test-vm-images-${{ steps.image-digest.outputs.digest }} + restore-keys: + cache-test-vm-images- + + - name: Download test VM images + if: github.ref_name == 'main' + run: mage test:fixtureVMImages \ No newline at end of file diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index dc7d825af1c8..b423b61699fb 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -92,8 +92,7 @@ jobs: echo "digest=$DIGEST" >> $GITHUB_OUTPUT - name: Restore test images from cache - uses: actions/cache@v4 - id: restore-test-images + uses: actions/cache/restore@v4 with: path: integration/testdata/fixtures/images key: cache-test-images-${{ steps.image-digest.outputs.digest }} @@ -148,8 +147,7 @@ jobs: echo "digest=$DIGEST" >> $GITHUB_OUTPUT - name: Restore test images from cache - uses: actions/cache@v4 - id: restore-test-images + uses: actions/cache/restore@v4 with: path: integration/testdata/fixtures/images key: cache-test-images-${{ steps.image-digest.outputs.digest }} @@ -185,8 +183,7 @@ jobs: echo "digest=$DIGEST" >> $GITHUB_OUTPUT - name: Restore test VM images from cache - uses: actions/cache@v4 - id: restore-test-vm-images + uses: actions/cache/restore@v4 with: path: integration/testdata/fixtures/vm-images key: cache-test-vm-images-${{ steps.image-digest.outputs.digest }} From 9d1be410c4ba4150f04dddb85b51aef747e9bf75 Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Mon, 30 Sep 2024 15:22:59 +0400 Subject: [PATCH 20/94] refactor: fix auth error handling (#7615) Signed-off-by: knqyf263 --- internal/dbtest/fake.go | 5 +-- pkg/db/db.go | 43 ++++++++++--------------- pkg/fanal/artifact/image/remote_sbom.go | 5 +-- pkg/javadb/client.go | 7 ++-- pkg/module/command.go | 8 ++--- pkg/oci/artifact.go | 4 +-- pkg/oci/artifact_test.go | 4 +-- pkg/policy/policy.go | 18 +++-------- pkg/policy/policy_test.go | 12 ++----- 9 files changed, 33 insertions(+), 73 deletions(-) diff --git a/internal/dbtest/fake.go b/internal/dbtest/fake.go index 9f2484bbf94a..7943c72273e2 100644 --- a/internal/dbtest/fake.go +++ b/internal/dbtest/fake.go @@ -62,10 +62,7 @@ func NewFakeDB(t *testing.T, dbPath string, opts FakeDBOptions) *oci.Artifact { opt := ftypes.RegistryOptions{ Insecure: false, } - art, err := oci.NewArtifact("dummy", true, opt, oci.WithImage(img)) - require.NoError(t, err) - - return art + return oci.NewArtifact("dummy", true, opt, oci.WithImage(img)) } func ArchiveDir(t *testing.T, dir string) string { diff --git a/pkg/db/db.go b/pkg/db/db.go index e4af60d092c6..344b21b86e44 100644 --- a/pkg/db/db.go +++ b/pkg/db/db.go @@ -153,16 +153,23 @@ func (c *Client) Download(ctx context.Context, dst string, opt types.RegistryOpt log.Debug("No metadata file") } - art, err := c.initOCIArtifact(opt) - if err != nil { - return xerrors.Errorf("OCI artifact error: %w", err) - } - - if err = art.Download(ctx, dst, oci.DownloadOption{MediaType: dbMediaType}); err != nil { + art := c.initOCIArtifact(opt) + if err := art.Download(ctx, dst, oci.DownloadOption{MediaType: dbMediaType}); err != nil { + var terr *transport.Error + if errors.As(err, &terr) { + for _, diagnostic := range terr.Errors { + // For better user experience + if diagnostic.Code == transport.DeniedErrorCode || diagnostic.Code == transport.UnauthorizedErrorCode { + // e.g. https://aquasecurity.github.io/trivy/latest/docs/references/troubleshooting/#db + log.Warnf("See %s", doc.URL("/docs/references/troubleshooting/", "db")) + break + } + } + } return xerrors.Errorf("database download error: %w", err) } - if err = c.updateDownloadedAt(ctx, dst); err != nil { + if err := c.updateDownloadedAt(ctx, dst); err != nil { return xerrors.Errorf("failed to update downloaded_at: %w", err) } return nil @@ -194,27 +201,11 @@ func (c *Client) updateDownloadedAt(ctx context.Context, dbDir string) error { return nil } -func (c *Client) initOCIArtifact(opt types.RegistryOptions) (*oci.Artifact, error) { +func (c *Client) initOCIArtifact(opt types.RegistryOptions) *oci.Artifact { if c.artifact != nil { - return c.artifact, nil - } - - art, err := oci.NewArtifact(c.dbRepository.String(), c.quiet, opt) - if err != nil { - var terr *transport.Error - if errors.As(err, &terr) { - for _, diagnostic := range terr.Errors { - // For better user experience - if diagnostic.Code == transport.DeniedErrorCode || diagnostic.Code == transport.UnauthorizedErrorCode { - // e.g. https://aquasecurity.github.io/trivy/latest/docs/references/troubleshooting/#db - log.Warnf("See %s", doc.URL("/docs/references/troubleshooting/", "db")) - break - } - } - } - return nil, xerrors.Errorf("OCI artifact error: %w", err) + return c.artifact } - return art, nil + return oci.NewArtifact(c.dbRepository.String(), c.quiet, opt) } func (c *Client) ShowInfo() error { diff --git a/pkg/fanal/artifact/image/remote_sbom.go b/pkg/fanal/artifact/image/remote_sbom.go index 37303a9f7b05..e95fef23140c 100644 --- a/pkg/fanal/artifact/image/remote_sbom.go +++ b/pkg/fanal/artifact/image/remote_sbom.go @@ -87,10 +87,6 @@ func (a Artifact) inspectOCIReferrerSBOM(ctx context.Context) (artifact.Referenc func (a Artifact) parseReferrer(ctx context.Context, repo string, desc v1.Descriptor) (artifact.Reference, error) { const fileName string = "referrer.sbom" repoName := fmt.Sprintf("%s@%s", repo, desc.Digest) - referrer, err := oci.NewArtifact(repoName, true, a.artifactOption.ImageOption.RegistryOptions) - if err != nil { - return artifact.Reference{}, xerrors.Errorf("OCI error: %w", err) - } tmpDir, err := os.MkdirTemp("", "trivy-sbom-*") if err != nil { @@ -99,6 +95,7 @@ func (a Artifact) parseReferrer(ctx context.Context, repo string, desc v1.Descri defer os.RemoveAll(tmpDir) // Download SBOM to local filesystem + referrer := oci.NewArtifact(repoName, true, a.artifactOption.ImageOption.RegistryOptions) if err = referrer.Download(ctx, tmpDir, oci.DownloadOption{ MediaType: desc.ArtifactType, Filename: fileName, diff --git a/pkg/javadb/client.go b/pkg/javadb/client.go index 936c2d40c028..9f90a37ba231 100644 --- a/pkg/javadb/client.go +++ b/pkg/javadb/client.go @@ -59,11 +59,8 @@ func (u *Updater) Update() error { log.Info("Downloading the Java DB...") // TODO: support remote options - var a *oci.Artifact - if a, err = oci.NewArtifact(u.repo.String(), u.quiet, u.registryOption); err != nil { - return xerrors.Errorf("oci error: %w", err) - } - if err = a.Download(context.Background(), dbDir, oci.DownloadOption{MediaType: mediaType}); err != nil { + art := oci.NewArtifact(u.repo.String(), u.quiet, u.registryOption) + if err = art.Download(context.Background(), dbDir, oci.DownloadOption{MediaType: mediaType}); err != nil { return xerrors.Errorf("DB download error: %w", err) } diff --git a/pkg/module/command.go b/pkg/module/command.go index 87a87e5d6209..2dd955aa0e4b 100644 --- a/pkg/module/command.go +++ b/pkg/module/command.go @@ -23,15 +23,11 @@ func Install(ctx context.Context, dir, repo string, quiet bool, opt types.Regist } log.Info("Installing the module from the repository...", log.String("repo", repo)) - artifact, err := oci.NewArtifact(repo, quiet, opt) - if err != nil { - return xerrors.Errorf("module initialize error: %w", err) - } + art := oci.NewArtifact(repo, quiet, opt) dst := filepath.Join(dir, ref.Context().Name()) log.Debug("Installing the module...", log.String("dst", dst)) - - if err = artifact.Download(ctx, dst, oci.DownloadOption{MediaType: mediaType}); err != nil { + if err = art.Download(ctx, dst, oci.DownloadOption{MediaType: mediaType}); err != nil { return xerrors.Errorf("module download error: %w", err) } diff --git a/pkg/oci/artifact.go b/pkg/oci/artifact.go index 04d62ee15d36..d8474941b3f5 100644 --- a/pkg/oci/artifact.go +++ b/pkg/oci/artifact.go @@ -57,7 +57,7 @@ type Artifact struct { } // NewArtifact returns a new artifact -func NewArtifact(repo string, quiet bool, registryOpt types.RegistryOptions, opts ...Option) (*Artifact, error) { +func NewArtifact(repo string, quiet bool, registryOpt types.RegistryOptions, opts ...Option) *Artifact { art := &Artifact{ repository: repo, quiet: quiet, @@ -67,7 +67,7 @@ func NewArtifact(repo string, quiet bool, registryOpt types.RegistryOptions, opt for _, o := range opts { o(art) } - return art, nil + return art } func (a *Artifact) populate(ctx context.Context, opt types.RegistryOptions) error { diff --git a/pkg/oci/artifact_test.go b/pkg/oci/artifact_test.go index ddfe0304cc63..7cc8cd19d3c1 100644 --- a/pkg/oci/artifact_test.go +++ b/pkg/oci/artifact_test.go @@ -116,9 +116,7 @@ func TestArtifact_Download(t *testing.T) { }, }, nil) - artifact, err := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) - require.NoError(t, err) - + artifact := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) err = artifact.Download(context.Background(), tempDir, oci.DownloadOption{ MediaType: tt.mediaType, }) diff --git a/pkg/policy/policy.go b/pkg/policy/policy.go index 88af220d3cf6..c8c05cf067c7 100644 --- a/pkg/policy/policy.go +++ b/pkg/policy/policy.go @@ -89,23 +89,16 @@ func NewClient(cacheDir string, quiet bool, checkBundleRepo string, opts ...Opti }, nil } -func (c *Client) populateOCIArtifact(registryOpts types.RegistryOptions) error { +func (c *Client) populateOCIArtifact(registryOpts types.RegistryOptions) { if c.artifact == nil { log.Debug("Loading check bundle", log.String("repository", c.checkBundleRepo)) - art, err := oci.NewArtifact(c.checkBundleRepo, c.quiet, registryOpts) - if err != nil { - return xerrors.Errorf("OCI artifact error: %w", err) - } - c.artifact = art + c.artifact = oci.NewArtifact(c.checkBundleRepo, c.quiet, registryOpts) } - return nil } // DownloadBuiltinPolicies download default policies from GitHub Pages func (c *Client) DownloadBuiltinPolicies(ctx context.Context, registryOpts types.RegistryOptions) error { - if err := c.populateOCIArtifact(registryOpts); err != nil { - return xerrors.Errorf("OPA bundle error: %w", err) - } + c.populateOCIArtifact(registryOpts) dst := c.contentDir() if err := c.artifact.Download(ctx, dst, oci.DownloadOption{MediaType: policyMediaType}); err != nil { @@ -165,10 +158,7 @@ func (c *Client) NeedsUpdate(ctx context.Context, registryOpts types.RegistryOpt return false, nil } - if err = c.populateOCIArtifact(registryOpts); err != nil { - return false, xerrors.Errorf("OPA bundle error: %w", err) - } - + c.populateOCIArtifact(registryOpts) digest, err := c.artifact.Digest(ctx) if err != nil { return false, xerrors.Errorf("digest error: %w", err) diff --git a/pkg/policy/policy_test.go b/pkg/policy/policy_test.go index 8e1b175da483..4dbd6b9a7558 100644 --- a/pkg/policy/policy_test.go +++ b/pkg/policy/policy_test.go @@ -116,9 +116,7 @@ func TestClient_LoadBuiltinPolicies(t *testing.T) { }, nil) // Mock OCI artifact - art, err := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) - require.NoError(t, err) - + art := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) c, err := policy.NewClient(tt.cacheDir, true, "", policy.WithOCIArtifact(art)) require.NoError(t, err) @@ -257,9 +255,7 @@ func TestClient_NeedsUpdate(t *testing.T) { require.NoError(t, err) } - art, err := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) - require.NoError(t, err) - + art := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) c, err := policy.NewClient(tmpDir, true, "", policy.WithOCIArtifact(art), policy.WithClock(tt.clock)) require.NoError(t, err) @@ -361,9 +357,7 @@ func TestClient_DownloadBuiltinPolicies(t *testing.T) { }, nil) // Mock OCI artifact - art, err := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) - require.NoError(t, err) - + art := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) c, err := policy.NewClient(tempDir, true, "", policy.WithClock(tt.clock), policy.WithOCIArtifact(art)) require.NoError(t, err) From 60725f879ba014c5c57583db6afc290b78facae8 Mon Sep 17 00:00:00 2001 From: afdesk Date: Mon, 30 Sep 2024 18:42:46 +0600 Subject: [PATCH 21/94] feat(secret): enhance secret scanning for python binary files (#7223) Signed-off-by: knqyf263 Co-authored-by: knqyf263 --- docs/docs/scanner/secret.md | 4 +- pkg/fanal/analyzer/secret/secret.go | 28 ++++++++++--- pkg/fanal/analyzer/secret/secret_test.go | 25 ++++++++++++ .../secret/testdata/secret.cpython-310.pyc | Bin 0 -> 226 bytes pkg/fanal/secret/scanner.go | 10 ++++- pkg/fanal/utils/utils.go | 38 ++++++++++++++++++ 6 files changed, 96 insertions(+), 9 deletions(-) create mode 100755 pkg/fanal/analyzer/secret/testdata/secret.cpython-310.pyc diff --git a/docs/docs/scanner/secret.md b/docs/docs/scanner/secret.md index 49d8c8488ece..ea74ae64c930 100644 --- a/docs/docs/scanner/secret.md +++ b/docs/docs/scanner/secret.md @@ -3,7 +3,9 @@ Trivy scans any container image, filesystem and git repository to detect exposed secrets like passwords, api keys, and tokens. Secret scanning is enabled by default. -Trivy will scan every plaintext file, according to builtin rules or configuration. There are plenty of builtin rules: +Trivy will scan every plaintext file, according to builtin rules or configuration. Also, Trivy can detect secrets in compiled Python files (`.pyc`). + +There are plenty of builtin rules: - AWS access key - GCP service account diff --git a/pkg/fanal/analyzer/secret/secret.go b/pkg/fanal/analyzer/secret/secret.go index d2627a840c1b..bdb3e96d1428 100644 --- a/pkg/fanal/analyzer/secret/secret.go +++ b/pkg/fanal/analyzer/secret/secret.go @@ -54,6 +54,9 @@ var ( ".gz", ".gzip", ".tar", + } + + allowedBinaries = []string{ ".pyc", } ) @@ -63,6 +66,10 @@ func init() { analyzer.RegisterAnalyzer(NewSecretAnalyzer(secret.Scanner{}, "")) } +func allowedBinary(filename string) bool { + return slices.Contains(allowedBinaries, filepath.Ext(filename)) +} + // SecretAnalyzer is an analyzer for secrets type SecretAnalyzer struct { scanner secret.Scanner @@ -96,7 +103,7 @@ func (a *SecretAnalyzer) Init(opt analyzer.AnalyzerOptions) error { func (a *SecretAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) { // Do not scan binaries binary, err := utils.IsBinary(input.Content, input.Info.Size()) - if binary || err != nil { + if err != nil || (binary && !allowedBinary(input.FilePath)) { return nil, nil } @@ -104,12 +111,20 @@ func (a *SecretAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput log.WithPrefix("secret").Warn("The size of the scanned file is too large. It is recommended to use `--skip-files` for this file to avoid high memory consumption.", log.FilePath(input.FilePath), log.Int64("size (MB)", size/1048576)) } - content, err := io.ReadAll(input.Content) - if err != nil { - return nil, xerrors.Errorf("read error %s: %w", input.FilePath, err) - } + var content []byte - content = bytes.ReplaceAll(content, []byte("\r"), []byte("")) + if !binary { + content, err = io.ReadAll(input.Content) + if err != nil { + return nil, xerrors.Errorf("read error %s: %w", input.FilePath, err) + } + content = bytes.ReplaceAll(content, []byte("\r"), []byte("")) + } else { + content, err = utils.ExtractPrintableBytes(input.Content) + if err != nil { + return nil, xerrors.Errorf("binary read error %s: %w", input.FilePath, err) + } + } filePath := input.FilePath // Files extracted from the image have an empty input.Dir. @@ -122,6 +137,7 @@ func (a *SecretAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput result := a.scanner.Scan(secret.ScanArgs{ FilePath: filePath, Content: content, + Binary: binary, }) if len(result.Findings) == 0 { diff --git a/pkg/fanal/analyzer/secret/secret_test.go b/pkg/fanal/analyzer/secret/secret_test.go index 7cba1d137e8f..5187ebc341bf 100644 --- a/pkg/fanal/analyzer/secret/secret_test.go +++ b/pkg/fanal/analyzer/secret/secret_test.go @@ -95,6 +95,16 @@ func TestSecretAnalyzer(t *testing.T) { }, }, } + wantFindingGH_PAT := types.SecretFinding{ + RuleID: "github-fine-grained-pat", + Category: "GitHub", + Title: "GitHub Fine-grained personal access tokens", + Severity: "CRITICAL", + StartLine: 1, + EndLine: 1, + Match: "Binary file \"/testdata/secret.cpython-310.pyc\" matches a rule \"GitHub Fine-grained personal access tokens\"", + } + tests := []struct { name string configPath string @@ -153,6 +163,21 @@ func TestSecretAnalyzer(t *testing.T) { filePath: "testdata/binaryfile", want: nil, }, + { + name: "python binary file", + configPath: "testdata/skip-tests-config.yaml", + filePath: "testdata/secret.cpython-310.pyc", + want: &analyzer.AnalysisResult{ + Secrets: []types.Secret{ + { + FilePath: "/testdata/secret.cpython-310.pyc", + Findings: []types.SecretFinding{ + wantFindingGH_PAT, + }, + }, + }, + }, + }, } for _, tt := range tests { diff --git a/pkg/fanal/analyzer/secret/testdata/secret.cpython-310.pyc b/pkg/fanal/analyzer/secret/testdata/secret.cpython-310.pyc new file mode 100755 index 0000000000000000000000000000000000000000..2bb659e7eb21abd1fed3da8d1f085600619d6f4b GIT binary patch literal 226 zcmd1j<>g`kf~l#i(<*@UV-N=!FabFZKwK;UBvKfn7*ZKi8JZax8B!R788n%0#inPL zWRxbw7bKR%8yY&fxVreddm0qydZb1gR(g7bC%VKZd6tJ1dsQZeB)a>Ag{D`fx>Xh# zI;KWsS45O#Mmjr(W*3&arFy3MmPa}Hc!rvIxca9?IfeN+R+jkzZD21>O)g3;F}%fE tP?VWhvXY^Q1?Uto@rzqeA0n$)P minLength { + // add a newline between printable lines to separate them + _ = currentPrintableLine.WriteByte('\n') + result = append(result, currentPrintableLine.Bytes()...) + } + currentPrintableLine.Reset() + } + if currentPrintableLine.Len() > minLength { + // add a newline between printable lines to separate them + _ = currentPrintableLine.WriteByte('\n') + result = append(result, currentPrintableLine.Bytes()...) + } + return result, nil +} From b8362321adb2af220830c5de31c29978423d47da Mon Sep 17 00:00:00 2001 From: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Date: Mon, 30 Sep 2024 20:47:51 +0600 Subject: [PATCH 22/94] feat(java): add empty versions if `pom.xml` dependency versions can't be detected (#7520) Co-authored-by: Teppei Fukuda --- docs/docs/coverage/language/java.md | 11 ++++++ pkg/dependency/parser/java/pom/artifact.go | 21 +++++++++-- pkg/dependency/parser/java/pom/parse.go | 8 +++++ pkg/dependency/parser/java/pom/parse_test.go | 35 +++++++++++++++++++ .../pom/testdata/dep-without-version/pom.xml | 24 +++++++++++++ .../analyzer/language/java/pom/pom_test.go | 11 ++++++ 6 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 pkg/dependency/parser/java/pom/testdata/dep-without-version/pom.xml diff --git a/docs/docs/coverage/language/java.md b/docs/docs/coverage/language/java.md index 67cd8c135b9d..0ee39bbd3155 100644 --- a/docs/docs/coverage/language/java.md +++ b/docs/docs/coverage/language/java.md @@ -69,6 +69,16 @@ The vulnerability database will be downloaded anyway. !!! Warning Trivy may skip some dependencies (that were not found on your local machine) when the `--offline-scan` flag is passed. +### empty dependency version +There are cases when Trivy cannot determine the version of dependencies: + +- Unable to determine the version from the parent because the parent is not reachable; +- The dependency uses a [hard requirement][version-requirement] with more than one version. + +In these cases, Trivy uses an empty version for the dependency. + +!!! Warning + Trivy doesn't detect child dependencies for dependencies without a version. ### maven-invoker-plugin Typically, the integration tests directory (`**/[src|target]/it/*/pom.xml`) of [maven-invoker-plugin][maven-invoker-plugin] doesn't contain actual `pom.xml` files and should be skipped to avoid noise. @@ -120,3 +130,4 @@ Make sure that you have cache[^8] directory to find licenses from `*.pom` depend [maven-pom-repos]: https://maven.apache.org/settings.html#repositories [sbt-dependency-lock]: https://stringbean.github.io/sbt-dependency-lock [detection-priority]: ../../scanner/vulnerability.md#detection-priority +[version-requirement]: https://maven.apache.org/pom.html#dependency-version-requirement-specification diff --git a/pkg/dependency/parser/java/pom/artifact.go b/pkg/dependency/parser/java/pom/artifact.go index b2e97efb229b..73ebe6b21407 100644 --- a/pkg/dependency/parser/java/pom/artifact.go +++ b/pkg/dependency/parser/java/pom/artifact.go @@ -6,15 +6,22 @@ import ( "regexp" "slices" "strings" + "sync" "github.com/samber/lo" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/version/doc" ) var ( - varRegexp = regexp.MustCompile(`\${(\S+?)}`) + varRegexp = regexp.MustCompile(`\${(\S+?)}`) + emptyVersionWarn = sync.OnceFunc(func() { + log.WithPrefix("pom").Warn("Dependency version cannot be determined. Child dependencies will not be found.", + // e.g. https://aquasecurity.github.io/trivy/latest/docs/coverage/language/java/#empty-dependency-version + log.String("details", doc.URL("/docs/coverage/language/java/", "empty-dependency-version"))) + }) ) type artifact struct { @@ -42,7 +49,17 @@ func newArtifact(groupID, artifactID, version string, licenses []string, props m } func (a artifact) IsEmpty() bool { - return a.GroupID == "" || a.ArtifactID == "" || a.Version.String() == "" + if a.GroupID == "" || a.ArtifactID == "" { + return true + } + if a.Version.String() == "" { + emptyVersionWarn() + log.WithPrefix("pom").Debug("Dependency version cannot be determined.", + log.String("GroupID", a.GroupID), + log.String("ArtifactID", a.ArtifactID), + ) + } + return false } func (a artifact) Equal(o artifact) bool { diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go index 76ca37f2dd05..542abcac3c8a 100644 --- a/pkg/dependency/parser/java/pom/parse.go +++ b/pkg/dependency/parser/java/pom/parse.go @@ -292,6 +292,14 @@ func (p *Parser) resolve(art artifact, rootDepManagement []pomDependency) (analy return *result, nil } + // We can't resolve a dependency without a version. + // So let's just keep this dependency. + if art.Version.String() == "" { + return analysisResult{ + artifact: art, + }, nil + } + p.logger.Debug("Resolving...", log.String("group_id", art.GroupID), log.String("artifact_id", art.ArtifactID), log.String("version", art.Version.String())) pomContent, err := p.tryRepository(art.GroupID, art.ArtifactID, art.Version.String()) diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index 9fa97ffd3672..82604846a4f3 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -809,6 +809,17 @@ func TestPom_Parse(t *testing.T) { Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, + { + ID: "org.example:example-api", + Name: "org.example:example-api", + Relationship: ftypes.RelationshipDirect, + Locations: []ftypes.Location{ + { + StartLine: 28, + EndLine: 32, + }, + }, + }, }, }, { @@ -1499,6 +1510,30 @@ func TestPom_Parse(t *testing.T) { }, }, }, + { + name: "dependency without version", + inputFile: filepath.Join("testdata", "dep-without-version", "pom.xml"), + local: true, + want: []ftypes.Package{ + { + ID: "com.example:dep-without-version:1.0.0", + Name: "com.example:dep-without-version", + Version: "1.0.0", + Relationship: ftypes.RelationshipRoot, + }, + { + ID: "org.example:example-api", + Name: "org.example:example-api", + Relationship: ftypes.RelationshipDirect, + Locations: ftypes.Locations{ + { + StartLine: 19, + EndLine: 22, + }, + }, + }, + }, + }, // [INFO] com.example:root-depManagement-in-parent:jar:1.0.0 // [INFO] \- org.example:example-dependency:jar:2.0.0:compile // [INFO] \- org.example:example-api:jar:1.0.1:compile diff --git a/pkg/dependency/parser/java/pom/testdata/dep-without-version/pom.xml b/pkg/dependency/parser/java/pom/testdata/dep-without-version/pom.xml new file mode 100644 index 000000000000..d7da70dd4735 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/dep-without-version/pom.xml @@ -0,0 +1,24 @@ + + 4.0.0 + + no-parent + Parent not found + + + com.example + wrong-parent + 1.0.0 + + + com.example + dep-without-version + 1.0.0 + + + + org.example + example-api + + + diff --git a/pkg/fanal/analyzer/language/java/pom/pom_test.go b/pkg/fanal/analyzer/language/java/pom/pom_test.go index b3aaf43a82cf..ea147a4d1141 100644 --- a/pkg/fanal/analyzer/language/java/pom/pom_test.go +++ b/pkg/fanal/analyzer/language/java/pom/pom_test.go @@ -147,6 +147,17 @@ func Test_pomAnalyzer_Analyze(t *testing.T) { Licenses: []string{"Apache-2.0"}, Relationship: types.RelationshipRoot, }, + { + ID: "org.example:example-api", + Name: "org.example:example-api", + Relationship: types.RelationshipDirect, + Locations: []types.Location{ + { + StartLine: 21, + EndLine: 25, + }, + }, + }, }, }, }, From d4edeb5d62be55e01ab02387dd5f2206ffceb424 Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Tue, 1 Oct 2024 08:27:02 +0400 Subject: [PATCH 23/94] test: use loaded image names (#7617) Signed-off-by: knqyf263 --- integration/docker_engine_test.go | 209 ++++++++------------- internal/testutil/docker.go | 57 ++++++ pkg/fanal/test/integration/library_test.go | 100 ++++------ 3 files changed, 178 insertions(+), 188 deletions(-) create mode 100644 internal/testutil/docker.go diff --git a/integration/docker_engine_test.go b/integration/docker_engine_test.go index 7f9a3119a156..a543d22e466f 100644 --- a/integration/docker_engine_test.go +++ b/integration/docker_engine_test.go @@ -1,19 +1,16 @@ //go:build integration -// +build integration package integration import ( "context" - "io" "os" "strings" "testing" + "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/types" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/client" "github.com/stretchr/testify/require" ) @@ -23,7 +20,6 @@ func TestDockerEngine(t *testing.T) { } tests := []struct { name string - imageTag string invalidImage bool ignoreUnfixed bool ignoreStatus []string @@ -34,10 +30,9 @@ func TestDockerEngine(t *testing.T) { wantErr string }{ { - name: "alpine:3.9", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:alpine-39", - input: "testdata/fixtures/images/alpine-39.tar.gz", - golden: "testdata/alpine-39.json.golden", + name: "alpine:3.9", + input: "testdata/fixtures/images/alpine-39.tar.gz", + golden: "testdata/alpine-39.json.golden", }, { name: "alpine:3.9, with high and critical severity", @@ -45,13 +40,11 @@ func TestDockerEngine(t *testing.T) { "HIGH", "CRITICAL", }, - imageTag: "ghcr.io/aquasecurity/trivy-test-images:alpine-39", - input: "testdata/fixtures/images/alpine-39.tar.gz", - golden: "testdata/alpine-39-high-critical.json.golden", + input: "testdata/fixtures/images/alpine-39.tar.gz", + golden: "testdata/alpine-39-high-critical.json.golden", }, { - name: "alpine:3.9, with .trivyignore", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:alpine-39", + name: "alpine:3.9, with .trivyignore", ignoreIDs: []string{ "CVE-2019-1549", "CVE-2019-14697", @@ -60,167 +53,141 @@ func TestDockerEngine(t *testing.T) { golden: "testdata/alpine-39-ignore-cveids.json.golden", }, { - name: "alpine:3.10", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:alpine-310", - input: "testdata/fixtures/images/alpine-310.tar.gz", - golden: "testdata/alpine-310.json.golden", + name: "alpine:3.10", + input: "testdata/fixtures/images/alpine-310.tar.gz", + golden: "testdata/alpine-310.json.golden", }, { - name: "amazonlinux:1", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:amazon-1", - input: "testdata/fixtures/images/amazon-1.tar.gz", - golden: "testdata/amazon-1.json.golden", + name: "amazonlinux:1", + input: "testdata/fixtures/images/amazon-1.tar.gz", + golden: "testdata/amazon-1.json.golden", }, { - name: "amazonlinux:2", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:amazon-2", - input: "testdata/fixtures/images/amazon-2.tar.gz", - golden: "testdata/amazon-2.json.golden", + name: "amazonlinux:2", + input: "testdata/fixtures/images/amazon-2.tar.gz", + golden: "testdata/amazon-2.json.golden", }, { - name: "almalinux 8", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:almalinux-8", - input: "testdata/fixtures/images/almalinux-8.tar.gz", - golden: "testdata/almalinux-8.json.golden", + name: "almalinux 8", + input: "testdata/fixtures/images/almalinux-8.tar.gz", + golden: "testdata/almalinux-8.json.golden", }, { - name: "rocky linux 8", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:rockylinux-8", - input: "testdata/fixtures/images/rockylinux-8.tar.gz", - golden: "testdata/rockylinux-8.json.golden", + name: "rocky linux 8", + input: "testdata/fixtures/images/rockylinux-8.tar.gz", + golden: "testdata/rockylinux-8.json.golden", }, { - name: "centos 6", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:centos-6", - input: "testdata/fixtures/images/centos-6.tar.gz", - golden: "testdata/centos-6.json.golden", + name: "centos 6", + input: "testdata/fixtures/images/centos-6.tar.gz", + golden: "testdata/centos-6.json.golden", }, { - name: "centos 7", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:centos-7", - input: "testdata/fixtures/images/centos-7.tar.gz", - golden: "testdata/centos-7.json.golden", + name: "centos 7", + input: "testdata/fixtures/images/centos-7.tar.gz", + golden: "testdata/centos-7.json.golden", }, { name: "centos 7, with --ignore-unfixed option", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:centos-7", ignoreUnfixed: true, input: "testdata/fixtures/images/centos-7.tar.gz", golden: "testdata/centos-7-ignore-unfixed.json.golden", }, { name: "centos 7, with --ignore-status option", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:centos-7", ignoreStatus: []string{"will_not_fix"}, input: "testdata/fixtures/images/centos-7.tar.gz", golden: "testdata/centos-7-ignore-unfixed.json.golden", }, { name: "centos 7, with --ignore-unfixed option, with medium severity", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:centos-7", ignoreUnfixed: true, severity: []string{"MEDIUM"}, input: "testdata/fixtures/images/centos-7.tar.gz", golden: "testdata/centos-7-medium.json.golden", }, { - name: "registry.redhat.io/ubi7", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:ubi-7", - input: "testdata/fixtures/images/ubi-7.tar.gz", - golden: "testdata/ubi-7.json.golden", + name: "registry.redhat.io/ubi7", + input: "testdata/fixtures/images/ubi-7.tar.gz", + golden: "testdata/ubi-7.json.golden", }, { - name: "debian buster/10", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:debian-buster", - input: "testdata/fixtures/images/debian-buster.tar.gz", - golden: "testdata/debian-buster.json.golden", + name: "debian buster/10", + input: "testdata/fixtures/images/debian-buster.tar.gz", + golden: "testdata/debian-buster.json.golden", }, { name: "debian buster/10, with --ignore-unfixed option", ignoreUnfixed: true, - imageTag: "ghcr.io/aquasecurity/trivy-test-images:debian-buster", input: "testdata/fixtures/images/debian-buster.tar.gz", golden: "testdata/debian-buster-ignore-unfixed.json.golden", }, { name: "debian buster/10, with --ignore-status option", ignoreStatus: []string{"affected"}, - imageTag: "ghcr.io/aquasecurity/trivy-test-images:debian-buster", input: "testdata/fixtures/images/debian-buster.tar.gz", golden: "testdata/debian-buster-ignore-unfixed.json.golden", }, { - name: "debian stretch/9", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:debian-stretch", - input: "testdata/fixtures/images/debian-stretch.tar.gz", - golden: "testdata/debian-stretch.json.golden", + name: "debian stretch/9", + input: "testdata/fixtures/images/debian-stretch.tar.gz", + golden: "testdata/debian-stretch.json.golden", }, { - name: "distroless base", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:distroless-base", - input: "testdata/fixtures/images/distroless-base.tar.gz", - golden: "testdata/distroless-base.json.golden", + name: "distroless base", + input: "testdata/fixtures/images/distroless-base.tar.gz", + golden: "testdata/distroless-base.json.golden", }, { - name: "distroless python2.7", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:distroless-python27", - input: "testdata/fixtures/images/distroless-python27.tar.gz", - golden: "testdata/distroless-python27.json.golden", + name: "distroless python2.7", + input: "testdata/fixtures/images/distroless-python27.tar.gz", + golden: "testdata/distroless-python27.json.golden", }, { - name: "oracle linux 8", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:oraclelinux-8", - input: "testdata/fixtures/images/oraclelinux-8.tar.gz", - golden: "testdata/oraclelinux-8.json.golden", + name: "oracle linux 8", + input: "testdata/fixtures/images/oraclelinux-8.tar.gz", + golden: "testdata/oraclelinux-8.json.golden", }, { - name: "ubuntu 18.04", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:ubuntu-1804", - input: "testdata/fixtures/images/ubuntu-1804.tar.gz", - golden: "testdata/ubuntu-1804.json.golden", + name: "ubuntu 18.04", + input: "testdata/fixtures/images/ubuntu-1804.tar.gz", + golden: "testdata/ubuntu-1804.json.golden", }, { name: "ubuntu 18.04, with --ignore-unfixed option", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:ubuntu-1804", ignoreUnfixed: true, input: "testdata/fixtures/images/ubuntu-1804.tar.gz", golden: "testdata/ubuntu-1804-ignore-unfixed.json.golden", }, { - name: "opensuse leap 15.1", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:opensuse-leap-151", - input: "testdata/fixtures/images/opensuse-leap-151.tar.gz", - golden: "testdata/opensuse-leap-151.json.golden", + name: "opensuse leap 15.1", + input: "testdata/fixtures/images/opensuse-leap-151.tar.gz", + golden: "testdata/opensuse-leap-151.json.golden", }, { - name: "opensuse tumbleweed", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:opensuse-tumbleweed", - input: "testdata/fixtures/images/opensuse-tumbleweed.tar.gz", - golden: "testdata/opensuse-tumbleweed.json.golden", + name: "opensuse tumbleweed", + input: "testdata/fixtures/images/opensuse-tumbleweed.tar.gz", + golden: "testdata/opensuse-tumbleweed.json.golden", }, { - name: "sle micro rancher 5.4", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:sle-micro-rancher-5.4_ndb", - input: "testdata/fixtures/images/sle-micro-rancher-5.4_ndb.tar.gz", - golden: "testdata/sl-micro-rancher5.4.json.golden", + name: "sle micro rancher 5.4", + input: "testdata/fixtures/images/sle-micro-rancher-5.4_ndb.tar.gz", + golden: "testdata/sl-micro-rancher5.4.json.golden", }, { - name: "photon 3.0", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:photon-30", - input: "testdata/fixtures/images/photon-30.tar.gz", - golden: "testdata/photon-30.json.golden", + name: "photon 3.0", + input: "testdata/fixtures/images/photon-30.tar.gz", + golden: "testdata/photon-30.json.golden", }, { - name: "CBL-Mariner 1.0", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:mariner-1.0", - input: "testdata/fixtures/images/mariner-1.0.tar.gz", - golden: "testdata/mariner-1.0.json.golden", + name: "CBL-Mariner 1.0", + input: "testdata/fixtures/images/mariner-1.0.tar.gz", + golden: "testdata/mariner-1.0.json.golden", }, { - name: "busybox with Cargo.lock", - imageTag: "ghcr.io/aquasecurity/trivy-test-images:busybox-with-lockfile", - input: "testdata/fixtures/images/busybox-with-lockfile.tar.gz", - golden: "testdata/busybox-with-lockfile.json.golden", + name: "busybox with Cargo.lock", + input: "testdata/fixtures/images/busybox-with-lockfile.tar.gz", + golden: "testdata/busybox-with-lockfile.json.golden", }, { name: "sad path, invalid image", @@ -239,44 +206,27 @@ func TestDockerEngine(t *testing.T) { ctx := context.Background() defer ctx.Done() - cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - require.NoError(t, err) + cli := testutil.NewDockerClient(t) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if !tt.invalidImage { testfile, err := os.Open(tt.input) require.NoError(t, err, tt.name) + defer testfile.Close() - // ensure image doesnt already exists - _, _ = cli.ImageRemove(ctx, tt.input, image.RemoveOptions{ - Force: true, - PruneChildren: true, - }) + // Ensure image doesn't already exist + cli.ImageRemove(t, ctx, tt.input) - // load image into docker engine - res, err := cli.ImageLoad(ctx, testfile, true) - require.NoError(t, err, tt.name) - if _, err := io.Copy(io.Discard, res.Body); err != nil { - require.NoError(t, err, tt.name) - } - defer res.Body.Close() + // Load image into docker engine + loadedImage := cli.ImageLoad(t, ctx, tt.input) - // tag our image to something unique - err = cli.ImageTag(ctx, tt.imageTag, tt.input) + // Tag our image to something unique + err = cli.ImageTag(ctx, loadedImage, tt.input) require.NoError(t, err, tt.name) - // cleanup - t.Cleanup(func() { - _, _ = cli.ImageRemove(ctx, tt.input, image.RemoveOptions{ - Force: true, - PruneChildren: true, - }) - _, _ = cli.ImageRemove(ctx, tt.imageTag, image.RemoveOptions{ - Force: true, - PruneChildren: true, - }) - }) + // Cleanup + t.Cleanup(func() { cli.ImageRemove(t, ctx, tt.input) }) } osArgs := []string{ @@ -309,7 +259,7 @@ func TestDockerEngine(t *testing.T) { } if len(tt.ignoreIDs) != 0 { trivyIgnore := ".trivyignore" - err = os.WriteFile(trivyIgnore, []byte(strings.Join(tt.ignoreIDs, "\n")), 0444) + err := os.WriteFile(trivyIgnore, []byte(strings.Join(tt.ignoreIDs, "\n")), 0444) require.NoError(t, err, "failed to write .trivyignore") defer os.Remove(trivyIgnore) } @@ -320,7 +270,8 @@ func TestDockerEngine(t *testing.T) { wantErr: tt.wantErr, // Container field was removed in Docker Engine v26.0 // cf. https://github.com/docker/cli/blob/v26.1.3/docs/deprecated.md#container-and-containerconfig-fields-in-image-inspect - override: overrideFuncs(overrideUID, func(t *testing.T, want, _ *types.Report) { + override: overrideFuncs(overrideUID, func(t *testing.T, want, got *types.Report) { + got.Metadata.ImageConfig.Container = "" want.Metadata.ImageConfig.Container = "" }), }) diff --git a/internal/testutil/docker.go b/internal/testutil/docker.go new file mode 100644 index 000000000000..60e1bb3ab668 --- /dev/null +++ b/internal/testutil/docker.go @@ -0,0 +1,57 @@ +package testutil + +import ( + "context" + "encoding/json" + "os" + "strings" + "testing" + + "github.com/docker/docker/api/types/image" + "github.com/docker/docker/client" + "github.com/stretchr/testify/require" +) + +type DockerClient struct { + *client.Client +} + +func NewDockerClient(t *testing.T) *DockerClient { + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + require.NoError(t, err) + return &DockerClient{Client: cli} +} + +func (c *DockerClient) ImageLoad(t *testing.T, ctx context.Context, imageFile string) string { + t.Helper() + testfile, err := os.Open(imageFile) + require.NoError(t, err) + defer testfile.Close() + + // Load image into docker engine + res, err := c.Client.ImageLoad(ctx, testfile, true) + require.NoError(t, err) + defer res.Body.Close() + + // Parse the response and extract the loaded image name + var data struct { + Stream string `json:"stream"` + } + err = json.NewDecoder(res.Body).Decode(&data) + require.NoError(t, err) + loadedImage := strings.TrimPrefix(data.Stream, "Loaded image: ") + loadedImage = strings.TrimSpace(loadedImage) + require.NotEmpty(t, loadedImage, data.Stream) + + t.Cleanup(func() { c.ImageRemove(t, ctx, loadedImage) }) + + return loadedImage +} + +func (c *DockerClient) ImageRemove(t *testing.T, ctx context.Context, imageID string) { + t.Helper() + _, _ = c.Client.ImageRemove(ctx, imageID, image.RemoveOptions{ + Force: true, + PruneChildren: true, + }) +} diff --git a/pkg/fanal/test/integration/library_test.go b/pkg/fanal/test/integration/library_test.go index ea76c7965b3a..ebe17d6e2188 100644 --- a/pkg/fanal/test/integration/library_test.go +++ b/pkg/fanal/test/integration/library_test.go @@ -7,20 +7,13 @@ import ( "encoding/json" "flag" "fmt" - "io" "os" "sort" - "strings" "testing" - dimage "github.com/docker/docker/api/types/image" - "github.com/docker/docker/client" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/aquasecurity/trivy/pkg/fanal/analyzer" - + "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/cache" + "github.com/aquasecurity/trivy/pkg/fanal/analyzer" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/all" "github.com/aquasecurity/trivy/pkg/fanal/applier" "github.com/aquasecurity/trivy/pkg/fanal/artifact" @@ -29,6 +22,9 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/image" "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + _ "modernc.org/sqlite" ) @@ -36,7 +32,7 @@ var update = flag.Bool("update", false, "update golden files") type testCase struct { name string - remoteImageName string + imageTag string imageFile string wantOS types.OS wantPkgsFromCmds string @@ -45,63 +41,63 @@ type testCase struct { var tests = []testCase{ { - name: "happy path, alpine:3.10", - remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:alpine-310", - imageFile: "../../../../integration/testdata/fixtures/images/alpine-310.tar.gz", + name: "happy path, alpine:3.10", + imageTag: "alpine-310", + imageFile: "../../../../integration/testdata/fixtures/images/alpine-310.tar.gz", wantOS: types.OS{ Name: "3.10.2", Family: "alpine", }, }, { - name: "happy path, amazonlinux:2", - remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:amazon-2", - imageFile: "../../../../integration/testdata/fixtures/images/amazon-2.tar.gz", + name: "happy path, amazonlinux:2", + imageTag: "amazon-2", + imageFile: "../../../../integration/testdata/fixtures/images/amazon-2.tar.gz", wantOS: types.OS{ Name: "2 (Karoo)", Family: "amazon", }, }, { - name: "happy path, debian:buster", - remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:debian-buster", - imageFile: "../../../../integration/testdata/fixtures/images/debian-buster.tar.gz", + name: "happy path, debian:buster", + imageTag: "debian-buster", + imageFile: "../../../../integration/testdata/fixtures/images/debian-buster.tar.gz", wantOS: types.OS{ Name: "10.1", Family: "debian", }, }, { - name: "happy path, photon:3.0", - remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:photon-30", - imageFile: "../../../../integration/testdata/fixtures/images/photon-30.tar.gz", + name: "happy path, photon:3.0", + imageTag: "photon-30", + imageFile: "../../../../integration/testdata/fixtures/images/photon-30.tar.gz", wantOS: types.OS{ Name: "3.0", Family: "photon", }, }, { - name: "happy path, registry.redhat.io/ubi7", - remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:ubi-7", - imageFile: "../../../../integration/testdata/fixtures/images/ubi-7.tar.gz", + name: "happy path, registry.redhat.io/ubi7", + imageTag: "ubi-7", + imageFile: "../../../../integration/testdata/fixtures/images/ubi-7.tar.gz", wantOS: types.OS{ Name: "7.7", Family: "redhat", }, }, { - name: "happy path, opensuse leap 15.1", - remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:opensuse-leap-151", - imageFile: "../../../../integration/testdata/fixtures/images/opensuse-leap-151.tar.gz", + name: "happy path, opensuse leap 15.1", + imageTag: "opensuse-leap-151", + imageFile: "../../../../integration/testdata/fixtures/images/opensuse-leap-151.tar.gz", wantOS: types.OS{ Name: "15.1", Family: "opensuse.leap", }, }, { - name: "happy path, opensuse tumbleweed", - remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:opensuse-tumbleweed", - imageFile: "../../../../integration/testdata/fixtures/images/opensuse-tumbleweed.tar.gz", + name: "happy path, opensuse tumbleweed", + imageTag: "opensuse-tumbleweed", + imageFile: "../../../../integration/testdata/fixtures/images/opensuse-tumbleweed.tar.gz", wantOS: types.OS{ Name: "20240607", Family: "opensuse.tumbleweed", @@ -109,27 +105,27 @@ var tests = []testCase{ }, { // from registry.suse.com/suse/sle15:15.3.17.8.16 - name: "happy path, suse 15.3 (NDB)", - remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:suse-15.3_ndb", - imageFile: "../../../../integration/testdata/fixtures/images/suse-15.3_ndb.tar.gz", + name: "happy path, suse 15.3 (NDB)", + imageTag: "suse-15.3_ndb", + imageFile: "../../../../integration/testdata/fixtures/images/suse-15.3_ndb.tar.gz", wantOS: types.OS{ Name: "15.3", Family: "suse linux enterprise server", }, }, { - name: "happy path, Fedora 35", - remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:fedora-35", - imageFile: "../../../../integration/testdata/fixtures/images/fedora-35.tar.gz", + name: "happy path, Fedora 35", + imageTag: "fedora-35", + imageFile: "../../../../integration/testdata/fixtures/images/fedora-35.tar.gz", wantOS: types.OS{ Name: "35", Family: "fedora", }, }, { - name: "happy path, vulnimage with lock files", - remoteImageName: "ghcr.io/aquasecurity/trivy-test-images:vulnimage", - imageFile: "../../../../integration/testdata/fixtures/images/vulnimage.tar.gz", + name: "happy path, vulnimage with lock files", + imageTag: "vulnimage", + imageFile: "../../../../integration/testdata/fixtures/images/vulnimage.tar.gz", wantOS: types.OS{ Name: "3.7.1", Family: "alpine", @@ -145,6 +141,8 @@ func TestFanal_Library_DockerMode(t *testing.T) { if *update { t.Skipf("This test creates wrong golden file") } + + cli := testutil.NewDockerClient(t) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ctx := context.Background() @@ -153,20 +151,10 @@ func TestFanal_Library_DockerMode(t *testing.T) { c, err := cache.NewFSCache(d) require.NoError(t, err) - cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - require.NoError(t, err, tt.name) - - testfile, err := os.Open(tt.imageFile) - require.NoError(t, err) - - // load image into docker engine - resp, err := cli.ImageLoad(ctx, testfile, true) - require.NoError(t, err, tt.name) - _, err = io.Copy(io.Discard, resp.Body) - require.NoError(t, err, tt.name) + loadedImage := cli.ImageLoad(t, ctx, tt.imageFile) // Enable only dockerd scanning - img, cleanup, err := image.NewContainerImage(ctx, tt.remoteImageName, types.ImageOptions{ + img, cleanup, err := image.NewContainerImage(ctx, loadedImage, types.ImageOptions{ ImageSources: types.ImageSources{types.DockerImageSource}, }) require.NoError(t, err, tt.name) @@ -190,11 +178,6 @@ func TestFanal_Library_DockerMode(t *testing.T) { // clear Cache require.NoError(t, c.Clear(), tt.name) - - _, _ = cli.ImageRemove(ctx, tt.remoteImageName, dimage.RemoveOptions{ - Force: true, - PruneChildren: true, - }) }) } } @@ -249,8 +232,7 @@ func checkOSPackages(t *testing.T, detail types.ArtifactDetail, tc testCase) { // Sort OS packages for consistency sort.Sort(detail.Packages) - splitted := strings.Split(tc.remoteImageName, ":") - goldenFile := fmt.Sprintf("testdata/goldens/packages/%s.json.golden", splitted[len(splitted)-1]) + goldenFile := fmt.Sprintf("testdata/goldens/packages/%s.json.golden", tc.imageTag) if *update { b, err := json.MarshalIndent(detail.Packages, "", " ") From 7602d14654c2a4cca445439da7b93bfab4b6d872 Mon Sep 17 00:00:00 2001 From: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Date: Tue, 1 Oct 2024 13:40:20 +0600 Subject: [PATCH 24/94] ci: don't use cache for `setup-go` (#7622) --- .github/workflows/auto-update-labels.yaml | 1 + .github/workflows/cache-test-images.yaml | 2 ++ .github/workflows/test.yaml | 8 ++++++++ 3 files changed, 11 insertions(+) diff --git a/.github/workflows/auto-update-labels.yaml b/.github/workflows/auto-update-labels.yaml index 941e7b5db9df..0de6e41438b9 100644 --- a/.github/workflows/auto-update-labels.yaml +++ b/.github/workflows/auto-update-labels.yaml @@ -20,6 +20,7 @@ jobs: with: # cf. https://github.com/aquasecurity/trivy/pull/6711 go-version: ${{ env.GO_VERSION }} + cache: false - name: Install aqua tools uses: aquaproj/aqua-installer@v3.0.1 diff --git a/.github/workflows/cache-test-images.yaml b/.github/workflows/cache-test-images.yaml index da8aff10cfd2..a03dc683e3ae 100644 --- a/.github/workflows/cache-test-images.yaml +++ b/.github/workflows/cache-test-images.yaml @@ -16,6 +16,7 @@ jobs: uses: actions/setup-go@v5 with: go-version-file: go.mod + cache: false - name: Install tools uses: aquaproj/aqua-installer@v3.0.1 @@ -55,6 +56,7 @@ jobs: uses: actions/setup-go@v5 with: go-version-file: go.mod + cache: false - name: Install tools uses: aquaproj/aqua-installer@v3.0.1 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index b423b61699fb..74b0933c6ef6 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -26,6 +26,8 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} + cache: false + - name: go mod tidy run: | go mod tidy @@ -78,6 +80,7 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} + cache: false - name: Install tools uses: aquaproj/aqua-installer@v3.0.1 @@ -113,6 +116,7 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} + cache: false - name: Install tools uses: aquaproj/aqua-installer@v3.0.1 @@ -133,6 +137,7 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} + cache: false - name: Install tools uses: aquaproj/aqua-installer@v3.0.1 @@ -170,6 +175,8 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} + cache: false + - name: Install tools uses: aquaproj/aqua-installer@v3.0.1 with: @@ -210,6 +217,7 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} + cache: false - name: Determine GoReleaser ID id: goreleaser_id From 3562529ddfb26d301311ed450c192e17011353df Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Tue, 1 Oct 2024 19:16:06 +0600 Subject: [PATCH 25/94] feat: support multiple DB repositories for vulnerability and Java DB (#7605) Signed-off-by: nikpivkin --- .../configuration/cli/trivy_filesystem.md | 4 +- .../configuration/cli/trivy_image.md | 4 +- .../configuration/cli/trivy_kubernetes.md | 4 +- .../configuration/cli/trivy_repository.md | 4 +- .../configuration/cli/trivy_rootfs.md | 4 +- .../configuration/cli/trivy_sbom.md | 96 +++++++++---------- .../configuration/cli/trivy_server.md | 2 +- .../references/configuration/cli/trivy_vm.md | 4 +- .../references/configuration/config-file.md | 6 +- internal/dbtest/fake.go | 2 +- pkg/commands/app.go | 2 +- pkg/commands/artifact/run.go | 4 +- pkg/commands/operation/operation.go | 5 +- pkg/commands/server/run.go | 4 +- pkg/db/db.go | 52 +++++----- pkg/db/db_test.go | 2 +- pkg/fanal/analyzer/analyzer_test.go | 4 +- .../analyzer/language/java/jar/jar_test.go | 4 +- pkg/fanal/artifact/image/remote_sbom.go | 3 +- pkg/flag/db_flags.go | 80 +++++++++------- pkg/flag/db_flags_test.go | 72 +++++++++----- pkg/javadb/client.go | 34 ++++--- pkg/module/command.go | 4 +- pkg/oci/artifact.go | 67 +++++++++++-- pkg/oci/artifact_test.go | 3 +- pkg/policy/policy.go | 6 +- pkg/policy/policy_test.go | 6 +- pkg/rpc/server/listen.go | 22 ++--- 28 files changed, 301 insertions(+), 203 deletions(-) diff --git a/docs/docs/references/configuration/cli/trivy_filesystem.md b/docs/docs/references/configuration/cli/trivy_filesystem.md index e907c5d4f9d5..9944a2d618ff 100644 --- a/docs/docs/references/configuration/cli/trivy_filesystem.md +++ b/docs/docs/references/configuration/cli/trivy_filesystem.md @@ -29,7 +29,7 @@ trivy filesystem [flags] PATH --config-data strings specify paths from which data for the Rego checks will be recursively loaded --config-file-schemas strings specify paths to JSON configuration file schemas to determine that a file matches some configuration and pass the schema to Rego checks for type checking --custom-headers strings custom headers in client mode - --db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2") + --db-repository strings OCI repository(ies) to retrieve trivy-db in order of priority (default [ghcr.io/aquasecurity/trivy-db:2]) --dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages --detection-priority string specify the detection priority: - "precise": Prioritizes precise by minimizing false positives. @@ -56,7 +56,7 @@ trivy filesystem [flags] PATH --include-deprecated-checks include deprecated checks (default true) --include-dev-deps include development dependencies in the report (supported: npm, yarn) --include-non-failures include successes and exceptions, available with '--scanners misconfig' - --java-db-repository string OCI repository to retrieve trivy-java-db from (default "ghcr.io/aquasecurity/trivy-java-db:1") + --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --license-confidence-level float specify license classifier's confidence level (default 0.9) --license-full eagerly look for licenses in source code headers and license files --list-all-pkgs output all packages in the JSON report regardless of vulnerability diff --git a/docs/docs/references/configuration/cli/trivy_image.md b/docs/docs/references/configuration/cli/trivy_image.md index 156582f047ad..b63daffbf4ad 100644 --- a/docs/docs/references/configuration/cli/trivy_image.md +++ b/docs/docs/references/configuration/cli/trivy_image.md @@ -43,7 +43,7 @@ trivy image [flags] IMAGE_NAME --config-data strings specify paths from which data for the Rego checks will be recursively loaded --config-file-schemas strings specify paths to JSON configuration file schemas to determine that a file matches some configuration and pass the schema to Rego checks for type checking --custom-headers strings custom headers in client mode - --db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2") + --db-repository strings OCI repository(ies) to retrieve trivy-db in order of priority (default [ghcr.io/aquasecurity/trivy-db:2]) --dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages --detection-priority string specify the detection priority: - "precise": Prioritizes precise by minimizing false positives. @@ -74,7 +74,7 @@ trivy image [flags] IMAGE_NAME --include-deprecated-checks include deprecated checks (default true) --include-non-failures include successes and exceptions, available with '--scanners misconfig' --input string input file path instead of image name - --java-db-repository string OCI repository to retrieve trivy-java-db from (default "ghcr.io/aquasecurity/trivy-java-db:1") + --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --license-confidence-level float specify license classifier's confidence level (default 0.9) --license-full eagerly look for licenses in source code headers and license files --list-all-pkgs output all packages in the JSON report regardless of vulnerability diff --git a/docs/docs/references/configuration/cli/trivy_kubernetes.md b/docs/docs/references/configuration/cli/trivy_kubernetes.md index b7c626a7d476..35190b1b82b5 100644 --- a/docs/docs/references/configuration/cli/trivy_kubernetes.md +++ b/docs/docs/references/configuration/cli/trivy_kubernetes.md @@ -38,7 +38,7 @@ trivy kubernetes [flags] [CONTEXT] --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-data strings specify paths from which data for the Rego checks will be recursively loaded --config-file-schemas strings specify paths to JSON configuration file schemas to determine that a file matches some configuration and pass the schema to Rego checks for type checking - --db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2") + --db-repository strings OCI repository(ies) to retrieve trivy-db in order of priority (default [ghcr.io/aquasecurity/trivy-db:2]) --dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages --detection-priority string specify the detection priority: - "precise": Prioritizes precise by minimizing false positives. @@ -70,7 +70,7 @@ trivy kubernetes [flags] [CONTEXT] --include-kinds strings indicate the kinds included in scanning (example: node) --include-namespaces strings indicate the namespaces included in scanning (example: kube-system) --include-non-failures include successes and exceptions, available with '--scanners misconfig' - --java-db-repository string OCI repository to retrieve trivy-java-db from (default "ghcr.io/aquasecurity/trivy-java-db:1") + --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --k8s-version string specify k8s version to validate outdated api by it (example: 1.21.0) --kubeconfig string specify the kubeconfig file path to use --list-all-pkgs output all packages in the JSON report regardless of vulnerability diff --git a/docs/docs/references/configuration/cli/trivy_repository.md b/docs/docs/references/configuration/cli/trivy_repository.md index 04f3f26e919a..59e4f2c08cb0 100644 --- a/docs/docs/references/configuration/cli/trivy_repository.md +++ b/docs/docs/references/configuration/cli/trivy_repository.md @@ -29,7 +29,7 @@ trivy repository [flags] (REPO_PATH | REPO_URL) --config-data strings specify paths from which data for the Rego checks will be recursively loaded --config-file-schemas strings specify paths to JSON configuration file schemas to determine that a file matches some configuration and pass the schema to Rego checks for type checking --custom-headers strings custom headers in client mode - --db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2") + --db-repository strings OCI repository(ies) to retrieve trivy-db in order of priority (default [ghcr.io/aquasecurity/trivy-db:2]) --dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages --detection-priority string specify the detection priority: - "precise": Prioritizes precise by minimizing false positives. @@ -56,7 +56,7 @@ trivy repository [flags] (REPO_PATH | REPO_URL) --include-deprecated-checks include deprecated checks (default true) --include-dev-deps include development dependencies in the report (supported: npm, yarn) --include-non-failures include successes and exceptions, available with '--scanners misconfig' - --java-db-repository string OCI repository to retrieve trivy-java-db from (default "ghcr.io/aquasecurity/trivy-java-db:1") + --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --license-confidence-level float specify license classifier's confidence level (default 0.9) --license-full eagerly look for licenses in source code headers and license files --list-all-pkgs output all packages in the JSON report regardless of vulnerability diff --git a/docs/docs/references/configuration/cli/trivy_rootfs.md b/docs/docs/references/configuration/cli/trivy_rootfs.md index 0e0dfa54d448..6022f4589446 100644 --- a/docs/docs/references/configuration/cli/trivy_rootfs.md +++ b/docs/docs/references/configuration/cli/trivy_rootfs.md @@ -31,7 +31,7 @@ trivy rootfs [flags] ROOTDIR --config-data strings specify paths from which data for the Rego checks will be recursively loaded --config-file-schemas strings specify paths to JSON configuration file schemas to determine that a file matches some configuration and pass the schema to Rego checks for type checking --custom-headers strings custom headers in client mode - --db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2") + --db-repository strings OCI repository(ies) to retrieve trivy-db in order of priority (default [ghcr.io/aquasecurity/trivy-db:2]) --dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages --detection-priority string specify the detection priority: - "precise": Prioritizes precise by minimizing false positives. @@ -58,7 +58,7 @@ trivy rootfs [flags] ROOTDIR --ignorefile string specify .trivyignore file (default ".trivyignore") --include-deprecated-checks include deprecated checks (default true) --include-non-failures include successes and exceptions, available with '--scanners misconfig' - --java-db-repository string OCI repository to retrieve trivy-java-db from (default "ghcr.io/aquasecurity/trivy-java-db:1") + --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --license-confidence-level float specify license classifier's confidence level (default 0.9) --license-full eagerly look for licenses in source code headers and license files --list-all-pkgs output all packages in the JSON report regardless of vulnerability diff --git a/docs/docs/references/configuration/cli/trivy_sbom.md b/docs/docs/references/configuration/cli/trivy_sbom.md index 1b0df922c7fc..f09453845518 100644 --- a/docs/docs/references/configuration/cli/trivy_sbom.md +++ b/docs/docs/references/configuration/cli/trivy_sbom.md @@ -20,54 +20,54 @@ trivy sbom [flags] SBOM_PATH ### Options ``` - --cache-backend string [EXPERIMENTAL] cache backend (e.g. redis://localhost:6379) (default "memory") - --cache-ttl duration cache TTL when using redis as cache backend - --compliance string compliance report to generate - --custom-headers strings custom headers in client mode - --db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2") - --detection-priority string specify the detection priority: - - "precise": Prioritizes precise by minimizing false positives. - - "comprehensive": Aims to detect more security findings at the cost of potential false positives. - (precise,comprehensive) (default "precise") - --download-db-only download/update vulnerability database but don't run a scan - --download-java-db-only download/update Java index database but don't run a scan - --exit-code int specify exit code when any security issues are found - --exit-on-eol int exit with the specified code when the OS reaches end of service/life - --file-patterns strings specify config file patterns - -f, --format string format (table,json,template,sarif,cyclonedx,spdx,spdx-json,github,cosign-vuln) (default "table") - -h, --help help for sbom - --ignore-policy string specify the Rego file path to evaluate each vulnerability - --ignore-status strings comma-separated list of vulnerability status to ignore (unknown,not_affected,affected,fixed,under_investigation,will_not_fix,fix_deferred,end_of_life) - --ignore-unfixed display only fixed vulnerabilities - --ignored-licenses strings specify a list of license to ignore - --ignorefile string specify .trivyignore file (default ".trivyignore") - --java-db-repository string OCI repository to retrieve trivy-java-db from (default "ghcr.io/aquasecurity/trivy-java-db:1") - --list-all-pkgs output all packages in the JSON report regardless of vulnerability - --no-progress suppress progress bar - --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-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 - --redis-tls enable redis TLS with public certificates, if using redis as cache backend - --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") - --sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor) - --scanners strings comma-separated list of what security issues to detect (vuln,license) (default [vuln]) - --server string server address in client mode - -s, --severity strings severities of security issues to be displayed (UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL) (default [UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL]) - --show-suppressed [EXPERIMENTAL] show suppressed vulnerabilities - --skip-db-update skip updating vulnerability database - --skip-dirs strings specify the directories or glob patterns to skip - --skip-files strings specify the files or glob patterns to skip - --skip-java-db-update skip updating Java index database - --skip-vex-repo-update [EXPERIMENTAL] Skip VEX Repository update - -t, --template string output template - --token string for authentication in client/server mode - --token-header string specify a header name for token in client/server mode (default "Trivy-Token") - --vex strings [EXPERIMENTAL] VEX sources ("repo", "oci" or file path) + --cache-backend string [EXPERIMENTAL] cache backend (e.g. redis://localhost:6379) (default "memory") + --cache-ttl duration cache TTL when using redis as cache backend + --compliance string compliance report to generate + --custom-headers strings custom headers in client mode + --db-repository strings OCI repository(ies) to retrieve trivy-db in order of priority (default [ghcr.io/aquasecurity/trivy-db:2]) + --detection-priority string specify the detection priority: + - "precise": Prioritizes precise by minimizing false positives. + - "comprehensive": Aims to detect more security findings at the cost of potential false positives. + (precise,comprehensive) (default "precise") + --download-db-only download/update vulnerability database but don't run a scan + --download-java-db-only download/update Java index database but don't run a scan + --exit-code int specify exit code when any security issues are found + --exit-on-eol int exit with the specified code when the OS reaches end of service/life + --file-patterns strings specify config file patterns + -f, --format string format (table,json,template,sarif,cyclonedx,spdx,spdx-json,github,cosign-vuln) (default "table") + -h, --help help for sbom + --ignore-policy string specify the Rego file path to evaluate each vulnerability + --ignore-status strings comma-separated list of vulnerability status to ignore (unknown,not_affected,affected,fixed,under_investigation,will_not_fix,fix_deferred,end_of_life) + --ignore-unfixed display only fixed vulnerabilities + --ignored-licenses strings specify a list of license to ignore + --ignorefile string specify .trivyignore file (default ".trivyignore") + --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) + --list-all-pkgs output all packages in the JSON report regardless of vulnerability + --no-progress suppress progress bar + --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-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 + --redis-tls enable redis TLS with public certificates, if using redis as cache backend + --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") + --sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor) + --scanners strings comma-separated list of what security issues to detect (vuln,license) (default [vuln]) + --server string server address in client mode + -s, --severity strings severities of security issues to be displayed (UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL) (default [UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL]) + --show-suppressed [EXPERIMENTAL] show suppressed vulnerabilities + --skip-db-update skip updating vulnerability database + --skip-dirs strings specify the directories or glob patterns to skip + --skip-files strings specify the files or glob patterns to skip + --skip-java-db-update skip updating Java index database + --skip-vex-repo-update [EXPERIMENTAL] Skip VEX Repository update + -t, --template string output template + --token string for authentication in client/server mode + --token-header string specify a header name for token in client/server mode (default "Trivy-Token") + --vex strings [EXPERIMENTAL] VEX sources ("repo", "oci" or file path) ``` ### Options inherited from parent commands diff --git a/docs/docs/references/configuration/cli/trivy_server.md b/docs/docs/references/configuration/cli/trivy_server.md index 4291496e34f1..b7ada8f2c19b 100644 --- a/docs/docs/references/configuration/cli/trivy_server.md +++ b/docs/docs/references/configuration/cli/trivy_server.md @@ -22,7 +22,7 @@ trivy server [flags] ``` --cache-backend string [EXPERIMENTAL] cache backend (e.g. redis://localhost:6379) (default "fs") --cache-ttl duration cache TTL when using redis as cache backend - --db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2") + --db-repository strings OCI repository(ies) to retrieve trivy-db in order of priority (default [ghcr.io/aquasecurity/trivy-db:2]) --download-db-only download/update vulnerability database but don't run a scan --enable-modules strings [EXPERIMENTAL] module names to enable -h, --help help for server diff --git a/docs/docs/references/configuration/cli/trivy_vm.md b/docs/docs/references/configuration/cli/trivy_vm.md index fef17624222d..9b7f6a6fef43 100644 --- a/docs/docs/references/configuration/cli/trivy_vm.md +++ b/docs/docs/references/configuration/cli/trivy_vm.md @@ -27,7 +27,7 @@ trivy vm [flags] VM_IMAGE --compliance string compliance report to generate --config-file-schemas strings specify paths to JSON configuration file schemas to determine that a file matches some configuration and pass the schema to Rego checks for type checking --custom-headers strings custom headers in client mode - --db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2") + --db-repository strings OCI repository(ies) to retrieve trivy-db in order of priority (default [ghcr.io/aquasecurity/trivy-db:2]) --dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages --detection-priority string specify the detection priority: - "precise": Prioritizes precise by minimizing false positives. @@ -52,7 +52,7 @@ trivy vm [flags] VM_IMAGE --ignore-unfixed display only fixed vulnerabilities --ignorefile string specify .trivyignore file (default ".trivyignore") --include-non-failures include successes and exceptions, available with '--scanners misconfig' - --java-db-repository string OCI repository to retrieve trivy-java-db from (default "ghcr.io/aquasecurity/trivy-java-db:1") + --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --list-all-pkgs output all packages in the JSON report regardless of vulnerability --misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot]) --module-dir string specify directory to the wasm modules that will be loaded (default "$HOME/.trivy/modules") diff --git a/docs/docs/references/configuration/config-file.md b/docs/docs/references/configuration/config-file.md index b2b25e47689e..ae3a017fda05 100644 --- a/docs/docs/references/configuration/config-file.md +++ b/docs/docs/references/configuration/config-file.md @@ -104,7 +104,8 @@ db: download-only: false # Same as '--java-db-repository' - java-repository: "ghcr.io/aquasecurity/trivy-java-db:1" + java-repository: + - ghcr.io/aquasecurity/trivy-java-db:1 # Same as '--skip-java-db-update' java-skip-update: false @@ -113,7 +114,8 @@ db: no-progress: false # Same as '--db-repository' - repository: "ghcr.io/aquasecurity/trivy-db:2" + repository: + - ghcr.io/aquasecurity/trivy-db:2 # Same as '--skip-db-update' skip-update: false diff --git a/internal/dbtest/fake.go b/internal/dbtest/fake.go index 7943c72273e2..528c549bda7f 100644 --- a/internal/dbtest/fake.go +++ b/internal/dbtest/fake.go @@ -62,7 +62,7 @@ func NewFakeDB(t *testing.T, dbPath string, opts FakeDBOptions) *oci.Artifact { opt := ftypes.RegistryOptions{ Insecure: false, } - return oci.NewArtifact("dummy", true, opt, oci.WithImage(img)) + return oci.NewArtifact("dummy", opt, oci.WithImage(img)) } func ArchiveDir(t *testing.T, dir string) string { diff --git a/pkg/commands/app.go b/pkg/commands/app.go index a3fb6df353d9..23b44fdec553 100644 --- a/pkg/commands/app.go +++ b/pkg/commands/app.go @@ -624,7 +624,7 @@ func NewServerCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { // java-db only works on client side. serverFlags.DBFlagGroup.DownloadJavaDBOnly = nil // disable '--download-java-db-only' serverFlags.DBFlagGroup.SkipJavaDBUpdate = nil // disable '--skip-java-db-update' - serverFlags.DBFlagGroup.JavaDBRepository = nil // disable '--java-db-repository' + serverFlags.DBFlagGroup.JavaDBRepositories = nil // disable '--java-db-repository' cmd := &cobra.Command{ Use: "server [flags]", diff --git a/pkg/commands/artifact/run.go b/pkg/commands/artifact/run.go index fa454c0cd276..11c6ef6a3090 100644 --- a/pkg/commands/artifact/run.go +++ b/pkg/commands/artifact/run.go @@ -291,7 +291,7 @@ func (r *runner) initDB(ctx context.Context, opts flag.Options) error { // download the database file noProgress := opts.Quiet || opts.NoProgress - if err := operation.DownloadDB(ctx, opts.AppVersion, opts.CacheDir, opts.DBRepository, noProgress, opts.SkipDBUpdate, opts.RegistryOpts()); err != nil { + if err := operation.DownloadDB(ctx, opts.AppVersion, opts.CacheDir, opts.DBRepositories, noProgress, opts.SkipDBUpdate, opts.RegistryOpts()); err != nil { return err } @@ -321,7 +321,7 @@ func (r *runner) initJavaDB(opts flag.Options) error { // Update the Java DB noProgress := opts.Quiet || opts.NoProgress - javadb.Init(opts.CacheDir, opts.JavaDBRepository, opts.SkipJavaDBUpdate, noProgress, opts.RegistryOpts()) + javadb.Init(opts.CacheDir, opts.JavaDBRepositories, opts.SkipJavaDBUpdate, noProgress, opts.RegistryOpts()) if opts.DownloadJavaDBOnly { if err := javadb.Update(); err != nil { return xerrors.Errorf("Java DB error: %w", err) diff --git a/pkg/commands/operation/operation.go b/pkg/commands/operation/operation.go index 16aa72085949..7570c4393b69 100644 --- a/pkg/commands/operation/operation.go +++ b/pkg/commands/operation/operation.go @@ -21,14 +21,14 @@ import ( var mu sync.Mutex // DownloadDB downloads the DB -func DownloadDB(ctx context.Context, appVersion, cacheDir string, dbRepository name.Reference, quiet, skipUpdate bool, +func DownloadDB(ctx context.Context, appVersion, cacheDir string, dbRepositories []name.Reference, quiet, skipUpdate bool, opt ftypes.RegistryOptions) error { mu.Lock() defer mu.Unlock() ctx = log.WithContextPrefix(ctx, "db") dbDir := db.Dir(cacheDir) - client := db.NewClient(dbDir, quiet, db.WithDBRepository(dbRepository)) + client := db.NewClient(dbDir, quiet, db.WithDBRepository(dbRepositories)) needsUpdate, err := client.NeedsUpdate(ctx, appVersion, skipUpdate) if err != nil { return xerrors.Errorf("database error: %w", err) @@ -36,7 +36,6 @@ func DownloadDB(ctx context.Context, appVersion, cacheDir string, dbRepository n if needsUpdate { log.InfoContext(ctx, "Need to update DB") - log.InfoContext(ctx, "Downloading DB...", log.String("repository", dbRepository.String())) if err = client.Download(ctx, dbDir, opt); err != nil { return xerrors.Errorf("failed to download vulnerability DB: %w", err) } diff --git a/pkg/commands/server/run.go b/pkg/commands/server/run.go index 6c5316d7465a..e9187b3442f5 100644 --- a/pkg/commands/server/run.go +++ b/pkg/commands/server/run.go @@ -26,7 +26,7 @@ func Run(ctx context.Context, opts flag.Options) (err error) { defer cleanup() // download the database file - if err = operation.DownloadDB(ctx, opts.AppVersion, opts.CacheDir, opts.DBRepository, + if err = operation.DownloadDB(ctx, opts.AppVersion, opts.CacheDir, opts.DBRepositories, true, opts.SkipDBUpdate, opts.RegistryOpts()); err != nil { return err } @@ -50,6 +50,6 @@ func Run(ctx context.Context, opts flag.Options) (err error) { m.Register() server := rpcServer.NewServer(opts.AppVersion, opts.Listen, opts.CacheDir, opts.Token, opts.TokenHeader, - opts.PathPrefix, opts.DBRepository, opts.RegistryOpts()) + opts.PathPrefix, opts.DBRepositories, opts.RegistryOpts()) return server.ListenAndServe(ctx, cacheClient, opts.SkipDBUpdate) } diff --git a/pkg/db/db.go b/pkg/db/db.go index 344b21b86e44..f7ceb09af4c9 100644 --- a/pkg/db/db.go +++ b/pkg/db/db.go @@ -2,14 +2,13 @@ package db import ( "context" - "errors" "fmt" "os" "path/filepath" "time" "github.com/google/go-containerregistry/pkg/name" - "github.com/google/go-containerregistry/pkg/v1/remote/transport" + "github.com/samber/lo" "golang.org/x/xerrors" "github.com/aquasecurity/trivy-db/pkg/db" @@ -18,7 +17,6 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/oci" - "github.com/aquasecurity/trivy/pkg/version/doc" ) const ( @@ -27,8 +25,9 @@ const ( ) var ( - DefaultRepository = fmt.Sprintf("%s:%d", "ghcr.io/aquasecurity/trivy-db", db.SchemaVersion) - defaultRepository, _ = name.NewTag(DefaultRepository) + // GitHub Container Registry + DefaultGHCRRepository = fmt.Sprintf("%s:%d", "ghcr.io/aquasecurity/trivy-db", db.SchemaVersion) + defaultGHCRRepository = lo.Must(name.NewTag(DefaultGHCRRepository)) Init = db.Init Close = db.Close @@ -36,8 +35,8 @@ var ( ) type options struct { - artifact *oci.Artifact - dbRepository name.Reference + artifact *oci.Artifact + dbRepositories []name.Reference } // Option is a functional option @@ -51,9 +50,9 @@ func WithOCIArtifact(art *oci.Artifact) Option { } // WithDBRepository takes a dbRepository -func WithDBRepository(dbRepository name.Reference) Option { +func WithDBRepository(dbRepository []name.Reference) Option { return func(opts *options) { - opts.dbRepository = dbRepository + opts.dbRepositories = dbRepository } } @@ -73,7 +72,9 @@ func Dir(cacheDir string) string { // NewClient is the factory method for DB client func NewClient(dbDir string, quiet bool, opts ...Option) *Client { o := &options{ - dbRepository: defaultRepository, + dbRepositories: []name.Reference{ + defaultGHCRRepository, + }, } for _, opt := range opts { @@ -153,20 +154,8 @@ func (c *Client) Download(ctx context.Context, dst string, opt types.RegistryOpt log.Debug("No metadata file") } - art := c.initOCIArtifact(opt) - if err := art.Download(ctx, dst, oci.DownloadOption{MediaType: dbMediaType}); err != nil { - var terr *transport.Error - if errors.As(err, &terr) { - for _, diagnostic := range terr.Errors { - // For better user experience - if diagnostic.Code == transport.DeniedErrorCode || diagnostic.Code == transport.UnauthorizedErrorCode { - // e.g. https://aquasecurity.github.io/trivy/latest/docs/references/troubleshooting/#db - log.Warnf("See %s", doc.URL("/docs/references/troubleshooting/", "db")) - break - } - } - } - return xerrors.Errorf("database download error: %w", err) + if err := c.downloadDB(ctx, opt, dst); err != nil { + return xerrors.Errorf("OCI artifact error: %w", err) } if err := c.updateDownloadedAt(ctx, dst); err != nil { @@ -201,11 +190,20 @@ func (c *Client) updateDownloadedAt(ctx context.Context, dbDir string) error { return nil } -func (c *Client) initOCIArtifact(opt types.RegistryOptions) *oci.Artifact { +func (c *Client) initArtifacts(opt types.RegistryOptions) oci.Artifacts { if c.artifact != nil { - return c.artifact + return oci.Artifacts{c.artifact} } - return oci.NewArtifact(c.dbRepository.String(), c.quiet, opt) + return oci.NewArtifacts(c.dbRepositories, opt) +} + +func (c *Client) downloadDB(ctx context.Context, opt types.RegistryOptions, dst string) error { + log.Info("Downloading vulnerability DB...") + downloadOpt := oci.DownloadOption{MediaType: dbMediaType, Quiet: c.quiet} + if err := c.initArtifacts(opt).Download(ctx, dst, downloadOpt); err != nil { + return xerrors.Errorf("failed to download vulnerability DB: %w", err) + } + return nil } func (c *Client) ShowInfo() error { diff --git a/pkg/db/db_test.go b/pkg/db/db_test.go index ff5e36e2b194..f64c0dc4a5c6 100644 --- a/pkg/db/db_test.go +++ b/pkg/db/db_test.go @@ -159,7 +159,7 @@ func TestClient_Download(t *testing.T) { { name: "invalid gzip", input: "testdata/trivy.db", - wantErr: "unexpected EOF", + wantErr: "OCI artifact error: failed to download vulnerability DB", }, } diff --git a/pkg/fanal/analyzer/analyzer_test.go b/pkg/fanal/analyzer/analyzer_test.go index 313fccda7e94..d8f93c0aa420 100644 --- a/pkg/fanal/analyzer/analyzer_test.go +++ b/pkg/fanal/analyzer/analyzer_test.go @@ -623,9 +623,9 @@ func TestAnalyzerGroup_PostAnalyze(t *testing.T) { if tt.analyzerType == analyzer.TypeJar { // init java-trivy-db with skip update - repo, err := name.NewTag(javadb.DefaultRepository) + repo, err := name.NewTag(javadb.DefaultGHCRRepository) require.NoError(t, err) - javadb.Init("./language/java/jar/testdata", repo, true, false, types.RegistryOptions{Insecure: false}) + javadb.Init("./language/java/jar/testdata", []name.Reference{repo}, true, false, types.RegistryOptions{Insecure: false}) } ctx := context.Background() diff --git a/pkg/fanal/analyzer/language/java/jar/jar_test.go b/pkg/fanal/analyzer/language/java/jar/jar_test.go index 225737166c81..146b60c1bbd6 100644 --- a/pkg/fanal/analyzer/language/java/jar/jar_test.go +++ b/pkg/fanal/analyzer/language/java/jar/jar_test.go @@ -132,9 +132,9 @@ func Test_javaLibraryAnalyzer_Analyze(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // init java-trivy-db with skip update - repo, err := name.NewTag(javadb.DefaultRepository) + repo, err := name.NewTag(javadb.DefaultGHCRRepository) require.NoError(t, err) - javadb.Init("testdata", repo, true, false, types.RegistryOptions{Insecure: false}) + javadb.Init("testdata", []name.Reference{repo}, true, false, types.RegistryOptions{Insecure: false}) a := javaLibraryAnalyzer{} ctx := context.Background() diff --git a/pkg/fanal/artifact/image/remote_sbom.go b/pkg/fanal/artifact/image/remote_sbom.go index e95fef23140c..d07d9cafe3ac 100644 --- a/pkg/fanal/artifact/image/remote_sbom.go +++ b/pkg/fanal/artifact/image/remote_sbom.go @@ -95,10 +95,11 @@ func (a Artifact) parseReferrer(ctx context.Context, repo string, desc v1.Descri defer os.RemoveAll(tmpDir) // Download SBOM to local filesystem - referrer := oci.NewArtifact(repoName, true, a.artifactOption.ImageOption.RegistryOptions) + referrer := oci.NewArtifact(repoName, a.artifactOption.ImageOption.RegistryOptions) if err = referrer.Download(ctx, tmpDir, oci.DownloadOption{ MediaType: desc.ArtifactType, Filename: fileName, + Quiet: true, }); err != nil { return artifact.Reference{}, xerrors.Errorf("SBOM download error: %w", err) } diff --git a/pkg/flag/db_flags.go b/pkg/flag/db_flags.go index 352a0094be7c..df0d6c6f5194 100644 --- a/pkg/flag/db_flags.go +++ b/pkg/flag/db_flags.go @@ -50,17 +50,17 @@ var ( ConfigName: "db.no-progress", Usage: "suppress progress bar", } - DBRepositoryFlag = Flag[string]{ + DBRepositoryFlag = Flag[[]string]{ Name: "db-repository", ConfigName: "db.repository", - Default: db.DefaultRepository, - Usage: "OCI repository to retrieve trivy-db from", + Default: []string{db.DefaultGHCRRepository}, + Usage: "OCI repository(ies) to retrieve trivy-db in order of priority", } - JavaDBRepositoryFlag = Flag[string]{ + JavaDBRepositoryFlag = Flag[[]string]{ Name: "java-db-repository", ConfigName: "db.java-repository", - Default: javadb.DefaultRepository, - Usage: "OCI repository to retrieve trivy-java-db from", + Default: []string{javadb.DefaultGHCRRepository}, + Usage: "OCI repository(ies) to retrieve trivy-java-db in order of priority", } LightFlag = Flag[bool]{ Name: "light", @@ -78,8 +78,8 @@ type DBFlagGroup struct { DownloadJavaDBOnly *Flag[bool] SkipJavaDBUpdate *Flag[bool] NoProgress *Flag[bool] - DBRepository *Flag[string] - JavaDBRepository *Flag[string] + DBRepositories *Flag[[]string] + JavaDBRepositories *Flag[[]string] Light *Flag[bool] // deprecated } @@ -90,8 +90,8 @@ type DBOptions struct { DownloadJavaDBOnly bool SkipJavaDBUpdate bool NoProgress bool - DBRepository name.Reference - JavaDBRepository name.Reference + DBRepositories []name.Reference + JavaDBRepositories []name.Reference } // NewDBFlagGroup returns a default DBFlagGroup @@ -104,8 +104,8 @@ func NewDBFlagGroup() *DBFlagGroup { SkipJavaDBUpdate: SkipJavaDBUpdateFlag.Clone(), Light: LightFlag.Clone(), NoProgress: NoProgressFlag.Clone(), - DBRepository: DBRepositoryFlag.Clone(), - JavaDBRepository: JavaDBRepositoryFlag.Clone(), + DBRepositories: DBRepositoryFlag.Clone(), + JavaDBRepositories: JavaDBRepositoryFlag.Clone(), } } @@ -121,8 +121,8 @@ func (f *DBFlagGroup) Flags() []Flagger { f.DownloadJavaDBOnly, f.SkipJavaDBUpdate, f.NoProgress, - f.DBRepository, - f.JavaDBRepository, + f.DBRepositories, + f.JavaDBRepositories, f.Light, } } @@ -147,30 +147,21 @@ func (f *DBFlagGroup) ToOptions() (DBOptions, error) { return DBOptions{}, xerrors.New("--skip-java-db-update and --download-java-db-only options can not be specified both") } - var dbRepository, javaDBRepository name.Reference - var err error - if f.DBRepository != nil { - if dbRepository, err = name.ParseReference(f.DBRepository.Value(), name.WithDefaultTag("")); err != nil { - return DBOptions{}, xerrors.Errorf("invalid db repository: %w", err) - } - // Add the schema version if the tag is not specified for backward compatibility. - if t, ok := dbRepository.(name.Tag); ok && t.TagStr() == "" { - dbRepository = t.Tag(fmt.Sprint(db.SchemaVersion)) - log.Info("Adding schema version to the DB repository for backward compatibility", - log.String("repository", dbRepository.String())) + var dbRepositories, javaDBRepositories []name.Reference + for _, repo := range f.DBRepositories.Value() { + ref, err := parseRepository(repo, db.SchemaVersion) + if err != nil { + return DBOptions{}, xerrors.Errorf("invalid DB repository: %w", err) } + dbRepositories = append(dbRepositories, ref) } - if f.JavaDBRepository != nil { - if javaDBRepository, err = name.ParseReference(f.JavaDBRepository.Value(), name.WithDefaultTag("")); err != nil { + for _, repo := range f.JavaDBRepositories.Value() { + ref, err := parseRepository(repo, javadb.SchemaVersion) + if err != nil { return DBOptions{}, xerrors.Errorf("invalid javadb repository: %w", err) } - // Add the schema version if the tag is not specified for backward compatibility. - if t, ok := javaDBRepository.(name.Tag); ok && t.TagStr() == "" { - javaDBRepository = t.Tag(fmt.Sprint(javadb.SchemaVersion)) - log.Info("Adding schema version to the Java DB repository for backward compatibility", - log.String("repository", javaDBRepository.String())) - } + javaDBRepositories = append(javaDBRepositories, ref) } return DBOptions{ @@ -180,7 +171,26 @@ func (f *DBFlagGroup) ToOptions() (DBOptions, error) { DownloadJavaDBOnly: downloadJavaDBOnly, SkipJavaDBUpdate: skipJavaDBUpdate, NoProgress: f.NoProgress.Value(), - DBRepository: dbRepository, - JavaDBRepository: javaDBRepository, + DBRepositories: dbRepositories, + JavaDBRepositories: javaDBRepositories, }, nil } + +func parseRepository(repo string, dbSchemaVersion int) (name.Reference, error) { + dbRepository, err := name.ParseReference(repo, name.WithDefaultTag("")) + if err != nil { + return nil, err + } + + // Add the schema version if the tag is not specified for backward compatibility. + t, ok := dbRepository.(name.Tag) + if !ok || t.TagStr() != "" { + return dbRepository, nil + } + + dbRepository = t.Tag(fmt.Sprint(dbSchemaVersion)) + log.Info("Adding schema version to the DB repository for backward compatibility", + log.String("repository", dbRepository.String())) + + return dbRepository, nil +} diff --git a/pkg/flag/db_flags_test.go b/pkg/flag/db_flags_test.go index 2bbd5b00198c..4f742e74ed68 100644 --- a/pkg/flag/db_flags_test.go +++ b/pkg/flag/db_flags_test.go @@ -17,31 +17,34 @@ func TestDBFlagGroup_ToOptions(t *testing.T) { SkipDBUpdate bool DownloadDBOnly bool Light bool - DBRepository string - JavaDBRepository string + DBRepository []string + JavaDBRepository []string } tests := []struct { - name string - fields fields - want flag.DBOptions - wantLogs []string - assertion require.ErrorAssertionFunc + name string + fields fields + want flag.DBOptions + wantLogs []string + wantErr string }{ { name: "happy", fields: fields{ SkipDBUpdate: true, DownloadDBOnly: false, - DBRepository: "ghcr.io/aquasecurity/trivy-db", - JavaDBRepository: "ghcr.io/aquasecurity/trivy-java-db", + DBRepository: []string{"ghcr.io/aquasecurity/trivy-db"}, + JavaDBRepository: []string{"ghcr.io/aquasecurity/trivy-java-db"}, }, want: flag.DBOptions{ - SkipDBUpdate: true, - DownloadDBOnly: false, - DBRepository: name.Tag{}, // All fields are unexported - JavaDBRepository: name.Tag{}, // All fields are unexported + SkipDBUpdate: true, + DownloadDBOnly: false, + DBRepositories: []name.Reference{name.Tag{}}, // All fields are unexported + JavaDBRepositories: []name.Reference{name.Tag{}}, // All fields are unexported + }, + wantLogs: []string{ + `Adding schema version to the DB repository for backward compatibility repository="ghcr.io/aquasecurity/trivy-db:2"`, + `Adding schema version to the DB repository for backward compatibility repository="ghcr.io/aquasecurity/trivy-java-db:1"`, }, - assertion: require.NoError, }, { name: "sad", @@ -49,25 +52,36 @@ func TestDBFlagGroup_ToOptions(t *testing.T) { SkipDBUpdate: true, DownloadDBOnly: true, }, - assertion: func(t require.TestingT, err error, msgs ...any) { - require.ErrorContains(t, err, "--skip-db-update and --download-db-only options can not be specified both") - }, + wantErr: "--skip-db-update and --download-db-only options can not be specified both", }, { name: "invalid repo", fields: fields{ SkipDBUpdate: true, DownloadDBOnly: false, - DBRepository: "foo:bar:baz", + DBRepository: []string{"foo:bar:baz"}, }, - assertion: func(t require.TestingT, err error, msgs ...any) { - require.ErrorContains(t, err, "invalid db repository") + wantErr: "invalid DB repository", + }, + { + name: "multiple repos", + fields: fields{ + SkipDBUpdate: true, + DownloadDBOnly: false, + DBRepository: []string{"ghcr.io/aquasecurity/trivy-db:2", "gallery.ecr.aws/aquasecurity/trivy-db:2"}, + JavaDBRepository: []string{"ghcr.io/aquasecurity/trivy-java-db:1", "gallery.ecr.aws/aquasecurity/trivy-java-db:1"}, + }, + want: flag.DBOptions{ + SkipDBUpdate: true, + DownloadDBOnly: false, + DBRepositories: []name.Reference{name.Tag{}, name.Tag{}}, // All fields are unexported + JavaDBRepositories: []name.Reference{name.Tag{}, name.Tag{}}, // All fields are unexported }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - out := newLogger(log.LevelWarn) + out := newLogger(log.LevelInfo) viper.Set(flag.SkipDBUpdateFlag.ConfigName, tt.fields.SkipDBUpdate) viper.Set(flag.DownloadDBOnlyFlag.ConfigName, tt.fields.DownloadDBOnly) @@ -76,13 +90,19 @@ func TestDBFlagGroup_ToOptions(t *testing.T) { // Assert options f := &flag.DBFlagGroup{ - DownloadDBOnly: flag.DownloadDBOnlyFlag.Clone(), - SkipDBUpdate: flag.SkipDBUpdateFlag.Clone(), - DBRepository: flag.DBRepositoryFlag.Clone(), - JavaDBRepository: flag.JavaDBRepositoryFlag.Clone(), + DownloadDBOnly: flag.DownloadDBOnlyFlag.Clone(), + SkipDBUpdate: flag.SkipDBUpdateFlag.Clone(), + DBRepositories: flag.DBRepositoryFlag.Clone(), + JavaDBRepositories: flag.JavaDBRepositoryFlag.Clone(), } got, err := f.ToOptions() - tt.assertion(t, err) + if tt.wantErr != "" { + require.Error(t, err) + assert.ErrorContains(t, err, tt.wantErr) + return + } + require.NoError(t, err) + assert.EqualExportedValues(t, tt.want, got) // Assert log messages diff --git a/pkg/javadb/client.go b/pkg/javadb/client.go index 9f90a37ba231..8c7aa81df9a3 100644 --- a/pkg/javadb/client.go +++ b/pkg/javadb/client.go @@ -26,12 +26,15 @@ const ( mediaType = "application/vnd.aquasec.trivy.javadb.layer.v1.tar+gzip" ) -var DefaultRepository = fmt.Sprintf("%s:%d", "ghcr.io/aquasecurity/trivy-java-db", SchemaVersion) +var ( + // GitHub Container Registry + DefaultGHCRRepository = fmt.Sprintf("%s:%d", "ghcr.io/aquasecurity/trivy-java-db", SchemaVersion) +) var updater *Updater type Updater struct { - repo name.Reference + repos []name.Reference dbDir string skip bool quiet bool @@ -40,8 +43,7 @@ type Updater struct { } func (u *Updater) Update() error { - dbDir := u.dbDir - metac := db.NewMetadata(dbDir) + metac := db.NewMetadata(u.dbDir) meta, err := metac.Get() if err != nil { @@ -55,13 +57,9 @@ func (u *Updater) Update() error { if (meta.Version != SchemaVersion || !u.isNewDB(meta)) && !u.skip { // Download DB - log.Info("Java DB Repository", log.Any("repository", u.repo)) - log.Info("Downloading the Java DB...") - // TODO: support remote options - art := oci.NewArtifact(u.repo.String(), u.quiet, u.registryOption) - if err = art.Download(context.Background(), dbDir, oci.DownloadOption{MediaType: mediaType}); err != nil { - return xerrors.Errorf("DB download error: %w", err) + if err := u.downloadDB(); err != nil { + return xerrors.Errorf("OCI artifact error: %w", err) } // Parse the newly downloaded metadata.json @@ -96,9 +94,21 @@ func (u *Updater) isNewDB(meta db.Metadata) bool { return false } -func Init(cacheDir string, javaDBRepository name.Reference, skip, quiet bool, registryOption ftypes.RegistryOptions) { +func (u *Updater) downloadDB() error { + log.Info("Downloading Java DB...") + + artifacts := oci.NewArtifacts(u.repos, u.registryOption) + downloadOpt := oci.DownloadOption{MediaType: mediaType, Quiet: u.quiet} + if err := artifacts.Download(context.Background(), u.dbDir, downloadOpt); err != nil { + return xerrors.Errorf("failed to download vulnerability DB: %w", err) + } + + return xerrors.New("failed to download Java DB from any source") +} + +func Init(cacheDir string, javaDBRepositories []name.Reference, skip, quiet bool, registryOption ftypes.RegistryOptions) { updater = &Updater{ - repo: javaDBRepository, + repos: javaDBRepositories, dbDir: dbDir(cacheDir), skip: skip, quiet: quiet, diff --git a/pkg/module/command.go b/pkg/module/command.go index 2dd955aa0e4b..a74da8384c3f 100644 --- a/pkg/module/command.go +++ b/pkg/module/command.go @@ -23,11 +23,11 @@ func Install(ctx context.Context, dir, repo string, quiet bool, opt types.Regist } log.Info("Installing the module from the repository...", log.String("repo", repo)) - art := oci.NewArtifact(repo, quiet, opt) + art := oci.NewArtifact(repo, opt) dst := filepath.Join(dir, ref.Context().Name()) log.Debug("Installing the module...", log.String("dst", dst)) - if err = art.Download(ctx, dst, oci.DownloadOption{MediaType: mediaType}); err != nil { + if err = art.Download(ctx, dst, oci.DownloadOption{MediaType: mediaType, Quiet: quiet}); err != nil { return xerrors.Errorf("module download error: %w", err) } diff --git a/pkg/oci/artifact.go b/pkg/oci/artifact.go index d8474941b3f5..345149892a4e 100644 --- a/pkg/oci/artifact.go +++ b/pkg/oci/artifact.go @@ -2,6 +2,7 @@ package oci import ( "context" + "errors" "io" "os" "path/filepath" @@ -10,11 +11,15 @@ import ( "github.com/cheggaaa/pb/v3" "github.com/google/go-containerregistry/pkg/name" v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/remote/transport" + "github.com/samber/lo" "golang.org/x/xerrors" "github.com/aquasecurity/trivy/pkg/downloader" "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/remote" + "github.com/aquasecurity/trivy/pkg/version/doc" ) const ( @@ -48,7 +53,6 @@ func WithImage(img v1.Image) Option { type Artifact struct { m sync.Mutex repository string - quiet bool // For OCI registries types.RegistryOptions @@ -57,10 +61,9 @@ type Artifact struct { } // NewArtifact returns a new artifact -func NewArtifact(repo string, quiet bool, registryOpt types.RegistryOptions, opts ...Option) *Artifact { +func NewArtifact(repo string, registryOpt types.RegistryOptions, opts ...Option) *Artifact { art := &Artifact{ repository: repo, - quiet: quiet, RegistryOptions: registryOpt, } @@ -98,6 +101,7 @@ func (a *Artifact) populate(ctx context.Context, opt types.RegistryOptions) erro type DownloadOption struct { MediaType string // Accept any media type if not specified Filename string // Use the annotation if not specified + Quiet bool } func (a *Artifact) Download(ctx context.Context, dir string, opt DownloadOption) error { @@ -140,14 +144,14 @@ func (a *Artifact) Download(ctx context.Context, dir string, opt DownloadOption) return xerrors.Errorf("unacceptable media type: %s", string(layerMediaType)) } - if err = a.download(ctx, layer, fileName, dir); err != nil { + if err = a.download(ctx, layer, fileName, dir, opt.Quiet); err != nil { return xerrors.Errorf("oci download error: %w", err) } return nil } -func (a *Artifact) download(ctx context.Context, layer v1.Layer, fileName, dir string) error { +func (a *Artifact) download(ctx context.Context, layer v1.Layer, fileName, dir string, quiet bool) error { size, err := layer.Size() if err != nil { return xerrors.Errorf("size error: %w", err) @@ -161,7 +165,7 @@ func (a *Artifact) download(ctx context.Context, layer v1.Layer, fileName, dir s // Show progress bar bar := pb.Full.Start64(size) - if a.quiet { + if quiet { bar.SetWriter(io.Discard) } pr := bar.NewProxyReader(rc) @@ -207,3 +211,54 @@ func (a *Artifact) Digest(ctx context.Context) (string, error) { } return digest.String(), nil } + +type Artifacts []*Artifact + +// NewArtifacts returns a slice of artifacts. +func NewArtifacts(repos []name.Reference, opt types.RegistryOptions, opts ...Option) Artifacts { + return lo.Map(repos, func(r name.Reference, _ int) *Artifact { + return NewArtifact(r.String(), opt, opts...) + }) +} + +// Download downloads artifacts until one of them succeeds. +// Attempts to download next artifact if the first one fails due to a temporary error. +func (a Artifacts) Download(ctx context.Context, dst string, opt DownloadOption) error { + for i, art := range a { + log.Info("Downloading artifact...", log.String("repo", art.repository)) + err := art.Download(ctx, dst, opt) + if err == nil { + log.Info("Artifact successfully downloaded", log.String("repo", art.repository)) + return nil + } + + if !shouldTryOtherRepo(err) { + return xerrors.Errorf("failed to download artifact from %s: %w", art.repository, err) + } + log.Error("Failed to download artifact", log.String("repo", art.repository), log.Err(err)) + if i < len(a)-1 { + log.Info("Trying to download artifact from other repository...") + } + } + + return xerrors.New("failed to download artifact from any source") +} + +func shouldTryOtherRepo(err error) bool { + var terr *transport.Error + if !errors.As(err, &terr) { + return false + } + + for _, diagnostic := range terr.Errors { + // For better user experience + if diagnostic.Code == transport.DeniedErrorCode || diagnostic.Code == transport.UnauthorizedErrorCode { + // e.g. https://aquasecurity.github.io/trivy/latest/docs/references/troubleshooting/#db + log.Warnf("See %s", doc.URL("/docs/references/troubleshooting/", "db")) + break + } + } + + // try the following artifact only if a temporary error occurs + return terr.Temporary() +} diff --git a/pkg/oci/artifact_test.go b/pkg/oci/artifact_test.go index 7cc8cd19d3c1..a8ce6e542641 100644 --- a/pkg/oci/artifact_test.go +++ b/pkg/oci/artifact_test.go @@ -116,9 +116,10 @@ func TestArtifact_Download(t *testing.T) { }, }, nil) - artifact := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) + artifact := oci.NewArtifact("repo", ftypes.RegistryOptions{}, oci.WithImage(img)) err = artifact.Download(context.Background(), tempDir, oci.DownloadOption{ MediaType: tt.mediaType, + Quiet: true, }) if tt.wantErr != "" { assert.ErrorContains(t, err, tt.wantErr) diff --git a/pkg/policy/policy.go b/pkg/policy/policy.go index c8c05cf067c7..2dbe2fc1b89a 100644 --- a/pkg/policy/policy.go +++ b/pkg/policy/policy.go @@ -92,7 +92,7 @@ func NewClient(cacheDir string, quiet bool, checkBundleRepo string, opts ...Opti func (c *Client) populateOCIArtifact(registryOpts types.RegistryOptions) { if c.artifact == nil { log.Debug("Loading check bundle", log.String("repository", c.checkBundleRepo)) - c.artifact = oci.NewArtifact(c.checkBundleRepo, c.quiet, registryOpts) + c.artifact = oci.NewArtifact(c.checkBundleRepo, registryOpts) } } @@ -101,7 +101,9 @@ func (c *Client) DownloadBuiltinPolicies(ctx context.Context, registryOpts types c.populateOCIArtifact(registryOpts) dst := c.contentDir() - if err := c.artifact.Download(ctx, dst, oci.DownloadOption{MediaType: policyMediaType}); err != nil { + if err := c.artifact.Download(ctx, dst, + oci.DownloadOption{MediaType: policyMediaType, Quiet: c.quiet}, + ); err != nil { return xerrors.Errorf("download error: %w", err) } diff --git a/pkg/policy/policy_test.go b/pkg/policy/policy_test.go index 4dbd6b9a7558..f6875eb1c9cb 100644 --- a/pkg/policy/policy_test.go +++ b/pkg/policy/policy_test.go @@ -116,7 +116,7 @@ func TestClient_LoadBuiltinPolicies(t *testing.T) { }, nil) // Mock OCI artifact - art := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) + art := oci.NewArtifact("repo", ftypes.RegistryOptions{}, oci.WithImage(img)) c, err := policy.NewClient(tt.cacheDir, true, "", policy.WithOCIArtifact(art)) require.NoError(t, err) @@ -255,7 +255,7 @@ func TestClient_NeedsUpdate(t *testing.T) { require.NoError(t, err) } - art := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) + art := oci.NewArtifact("repo", ftypes.RegistryOptions{}, oci.WithImage(img)) c, err := policy.NewClient(tmpDir, true, "", policy.WithOCIArtifact(art), policy.WithClock(tt.clock)) require.NoError(t, err) @@ -357,7 +357,7 @@ func TestClient_DownloadBuiltinPolicies(t *testing.T) { }, nil) // Mock OCI artifact - art := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) + art := oci.NewArtifact("repo", ftypes.RegistryOptions{}, oci.WithImage(img)) c, err := policy.NewClient(tempDir, true, "", policy.WithClock(tt.clock), policy.WithOCIArtifact(art)) require.NoError(t, err) diff --git a/pkg/rpc/server/listen.go b/pkg/rpc/server/listen.go index f1e39fa1b2f0..c1bc5033530c 100644 --- a/pkg/rpc/server/listen.go +++ b/pkg/rpc/server/listen.go @@ -29,21 +29,21 @@ const updateInterval = 1 * time.Hour // Server represents Trivy server type Server struct { - appVersion string - addr string - cacheDir string - dbDir string - token string - tokenHeader string - pathPrefix string - dbRepository name.Reference + appVersion string + addr string + cacheDir string + dbDir string + token string + tokenHeader string + pathPrefix string + dbRepositories []name.Reference // For OCI registries types.RegistryOptions } // NewServer returns an instance of Server -func NewServer(appVersion, addr, cacheDir, token, tokenHeader, pathPrefix string, dbRepository name.Reference, opt types.RegistryOptions) Server { +func NewServer(appVersion, addr, cacheDir, token, tokenHeader, pathPrefix string, dbRepositories []name.Reference, opt types.RegistryOptions) Server { return Server{ appVersion: appVersion, addr: addr, @@ -52,7 +52,7 @@ func NewServer(appVersion, addr, cacheDir, token, tokenHeader, pathPrefix string token: token, tokenHeader: tokenHeader, pathPrefix: pathPrefix, - dbRepository: dbRepository, + dbRepositories: dbRepositories, RegistryOptions: opt, } } @@ -63,7 +63,7 @@ func (s Server) ListenAndServe(ctx context.Context, serverCache cache.Cache, ski dbUpdateWg := &sync.WaitGroup{} go func() { - worker := newDBWorker(db.NewClient(s.dbDir, true, db.WithDBRepository(s.dbRepository))) + worker := newDBWorker(db.NewClient(s.dbDir, true, db.WithDBRepository(s.dbRepositories))) for { time.Sleep(updateInterval) if err := worker.update(ctx, s.appVersion, s.dbDir, skipDBUpdate, dbUpdateWg, requestWg, s.RegistryOptions); err != nil { From c0e8da3828e9d3a0b30d1f6568037db8dc827765 Mon Sep 17 00:00:00 2001 From: simar7 <1254783+simar7@users.noreply.github.com> Date: Tue, 1 Oct 2024 23:20:03 -0600 Subject: [PATCH 26/94] feat(misconf): Support `--skip-*` for all included modules (#7579) Signed-off-by: nikpivkin Co-authored-by: nikpivkin --- pkg/commands/artifact/run.go | 2 + pkg/fanal/utils/utils.go | 27 ++++++ pkg/fanal/walker/fs.go | 7 +- pkg/fanal/walker/tar.go | 8 +- pkg/fanal/walker/vm.go | 5 +- pkg/fanal/walker/walk.go | 29 ------ pkg/fanal/walker/walk_test.go | 6 +- pkg/iac/scanners/terraform/options.go | 16 ++++ pkg/iac/scanners/terraform/parser/option.go | 12 +++ pkg/iac/scanners/terraform/parser/parser.go | 7 ++ pkg/iac/scanners/terraform/scanner_test.go | 99 +++++++++++++++++++++ pkg/misconf/scanner.go | 4 + 12 files changed, 181 insertions(+), 41 deletions(-) diff --git a/pkg/commands/artifact/run.go b/pkg/commands/artifact/run.go index 11c6ef6a3090..6f926519b91a 100644 --- a/pkg/commands/artifact/run.go +++ b/pkg/commands/artifact/run.go @@ -659,5 +659,7 @@ func initMisconfScannerOption(opts flag.Options) (misconf.ScannerOption, error) TfExcludeDownloaded: opts.TfExcludeDownloaded, FilePatterns: opts.FilePatterns, ConfigFileSchemas: configSchemas, + SkipFiles: opts.SkipFiles, + SkipDirs: opts.SkipDirs, }, nil } diff --git a/pkg/fanal/utils/utils.go b/pkg/fanal/utils/utils.go index 58b44510db89..463c8dd1f255 100644 --- a/pkg/fanal/utils/utils.go +++ b/pkg/fanal/utils/utils.go @@ -9,10 +9,14 @@ import ( "os" "os/exec" "path/filepath" + "strings" "unicode" + "github.com/bmatcuk/doublestar/v4" + "github.com/samber/lo" "golang.org/x/xerrors" + "github.com/aquasecurity/trivy/pkg/log" xio "github.com/aquasecurity/trivy/pkg/x/io" ) @@ -98,6 +102,29 @@ func IsBinary(content xio.ReadSeekerAt, fileSize int64) (bool, error) { return false, nil } +func CleanSkipPaths(skipPaths []string) []string { + return lo.Map(skipPaths, func(skipPath string, index int) string { + skipPath = filepath.ToSlash(filepath.Clean(skipPath)) + return strings.TrimLeft(skipPath, "/") + }) +} + +func SkipPath(path string, skipPaths []string) bool { + path = strings.TrimLeft(path, "/") + + // skip files + for _, pattern := range skipPaths { + match, err := doublestar.Match(pattern, path) + if err != nil { + return false // return early if bad pattern + } else if match { + log.Debug("Skipping path", log.String("path", path)) + return true + } + } + return false +} + func ExtractPrintableBytes(content xio.ReadSeekerAt) ([]byte, error) { const minLength = 4 // Minimum length of strings to extract var result []byte diff --git a/pkg/fanal/walker/fs.go b/pkg/fanal/walker/fs.go index f6bec84d1fc2..3ebfb7258459 100644 --- a/pkg/fanal/walker/fs.go +++ b/pkg/fanal/walker/fs.go @@ -9,6 +9,7 @@ import ( "golang.org/x/xerrors" + "github.com/aquasecurity/trivy/pkg/fanal/utils" "github.com/aquasecurity/trivy/pkg/log" xio "github.com/aquasecurity/trivy/pkg/x/io" ) @@ -53,13 +54,13 @@ func (w *FS) WalkDirFunc(root string, fn WalkFunc, opt Option) fs.WalkDirFunc { // Skip unnecessary files switch { case d.IsDir(): - if SkipPath(relPath, opt.SkipDirs) { + if utils.SkipPath(relPath, opt.SkipDirs) { return filepath.SkipDir } return nil case !d.Type().IsRegular(): return nil - case SkipPath(relPath, opt.SkipFiles): + case utils.SkipPath(relPath, opt.SkipFiles): return nil } @@ -148,7 +149,7 @@ func (w *FS) BuildSkipPaths(base string, paths []string) []string { relativePaths = append(relativePaths, relPath) } - relativePaths = CleanSkipPaths(relativePaths) + relativePaths = utils.CleanSkipPaths(relativePaths) return relativePaths } diff --git a/pkg/fanal/walker/tar.go b/pkg/fanal/walker/tar.go index 51f185d89c50..0c7d0bee9d5d 100644 --- a/pkg/fanal/walker/tar.go +++ b/pkg/fanal/walker/tar.go @@ -27,8 +27,8 @@ type LayerTar struct { func NewLayerTar(opt Option) LayerTar { return LayerTar{ - skipFiles: CleanSkipPaths(opt.SkipFiles), - skipDirs: CleanSkipPaths(opt.SkipDirs), + skipFiles: utils.CleanSkipPaths(opt.SkipFiles), + skipDirs: utils.CleanSkipPaths(opt.SkipDirs), } } @@ -63,12 +63,12 @@ func (w LayerTar) Walk(layer io.Reader, analyzeFn WalkFunc) ([]string, []string, switch hdr.Typeflag { case tar.TypeDir: - if SkipPath(filePath, w.skipDirs) { + if utils.SkipPath(filePath, w.skipDirs) { skippedDirs = append(skippedDirs, filePath) continue } case tar.TypeReg: - if SkipPath(filePath, w.skipFiles) { + if utils.SkipPath(filePath, w.skipFiles) { continue } // symlinks and hardlinks have no content in reader, skip them diff --git a/pkg/fanal/walker/vm.go b/pkg/fanal/walker/vm.go index 0bc3e87ac86d..f8ef63ce0252 100644 --- a/pkg/fanal/walker/vm.go +++ b/pkg/fanal/walker/vm.go @@ -17,6 +17,7 @@ import ( "github.com/masahiro331/go-xfs-filesystem/xfs" "golang.org/x/xerrors" + "github.com/aquasecurity/trivy/pkg/fanal/utils" "github.com/aquasecurity/trivy/pkg/fanal/vm/filesystem" "github.com/aquasecurity/trivy/pkg/log" xio "github.com/aquasecurity/trivy/pkg/x/io" @@ -131,13 +132,13 @@ func (w *VM) fsWalk(fsys fs.FS, path string, d fs.DirEntry, err error) error { pathName := strings.TrimPrefix(filepath.Clean(path), "/") switch { case fi.IsDir(): - if SkipPath(pathName, w.skipDirs) { + if utils.SkipPath(pathName, w.skipDirs) { return filepath.SkipDir } return nil case !fi.Mode().IsRegular(): return nil - case SkipPath(pathName, w.skipFiles): + case utils.SkipPath(pathName, w.skipFiles): return nil case fi.Mode()&0x1000 == 0x1000 || fi.Mode()&0x2000 == 0x2000 || diff --git a/pkg/fanal/walker/walk.go b/pkg/fanal/walker/walk.go index 52c13808d86b..0785cef41606 100644 --- a/pkg/fanal/walker/walk.go +++ b/pkg/fanal/walker/walk.go @@ -2,14 +2,8 @@ package walker import ( "os" - "path/filepath" - "strings" - - "github.com/bmatcuk/doublestar/v4" - "github.com/samber/lo" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" - "github.com/aquasecurity/trivy/pkg/log" ) const defaultSizeThreshold = int64(100) << 20 // 200MB @@ -27,26 +21,3 @@ type Option struct { } type WalkFunc func(filePath string, info os.FileInfo, opener analyzer.Opener) error - -func CleanSkipPaths(skipPaths []string) []string { - return lo.Map(skipPaths, func(skipPath string, index int) string { - skipPath = filepath.ToSlash(filepath.Clean(skipPath)) - return strings.TrimLeft(skipPath, "/") - }) -} - -func SkipPath(path string, skipPaths []string) bool { - path = strings.TrimLeft(path, "/") - - // skip files - for _, pattern := range skipPaths { - match, err := doublestar.Match(pattern, path) - if err != nil { - return false // return early if bad pattern - } else if match { - log.Debug("Skipping path", log.String("path", path)) - return true - } - } - return false -} diff --git a/pkg/fanal/walker/walk_test.go b/pkg/fanal/walker/walk_test.go index 0bac6009d04f..09d55527c0fe 100644 --- a/pkg/fanal/walker/walk_test.go +++ b/pkg/fanal/walker/walk_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/aquasecurity/trivy/pkg/fanal/walker" + "github.com/aquasecurity/trivy/pkg/fanal/utils" ) func TestSkipFile(t *testing.T) { @@ -64,7 +64,7 @@ func TestSkipFile(t *testing.T) { t.Run(tt.name, func(t *testing.T) { for file, want := range tt.wants { file = filepath.ToSlash(filepath.Clean(file)) - got := walker.SkipPath(file, walker.CleanSkipPaths(tt.skipFiles)) + got := utils.SkipPath(file, utils.CleanSkipPaths(tt.skipFiles)) assert.Equal(t, want, got, fmt.Sprintf("skipFiles: %s, file: %s", tt.skipFiles, file)) } }) @@ -138,7 +138,7 @@ func TestSkipDir(t *testing.T) { t.Run(tt.name, func(t *testing.T) { for dir, want := range tt.wants { dir = filepath.ToSlash(filepath.Clean(dir)) - got := walker.SkipPath(dir, walker.CleanSkipPaths(tt.skipDirs)) + got := utils.SkipPath(dir, utils.CleanSkipPaths(tt.skipDirs)) assert.Equal(t, want, got, fmt.Sprintf("defaultSkipDirs: %s, dir: %s", tt.skipDirs, dir)) } }) diff --git a/pkg/iac/scanners/terraform/options.go b/pkg/iac/scanners/terraform/options.go index d256f0a34daa..5a665a05638f 100644 --- a/pkg/iac/scanners/terraform/options.go +++ b/pkg/iac/scanners/terraform/options.go @@ -84,3 +84,19 @@ func ScannerWithConfigsFileSystem(fsys fs.FS) options.ScannerOption { } } } + +func ScannerWithSkipFiles(files []string) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if tf, ok := s.(ConfigurableTerraformScanner); ok { + tf.AddParserOptions(parser.OptionWithSkipFiles(files)) + } + } +} + +func ScannerWithSkipDirs(dirs []string) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if tf, ok := s.(ConfigurableTerraformScanner); ok { + tf.AddParserOptions(parser.OptionWithSkipDirs(dirs)) + } + } +} diff --git a/pkg/iac/scanners/terraform/parser/option.go b/pkg/iac/scanners/terraform/parser/option.go index 277cf2a58c61..f9ada6545225 100644 --- a/pkg/iac/scanners/terraform/parser/option.go +++ b/pkg/iac/scanners/terraform/parser/option.go @@ -49,3 +49,15 @@ func OptionWithConfigsFS(fsys fs.FS) Option { p.configsFS = fsys } } + +func OptionWithSkipFiles(files []string) Option { + return func(p *Parser) { + p.skipPaths = files + } +} + +func OptionWithSkipDirs(dirs []string) Option { + return func(p *Parser) { + p.skipPaths = dirs + } +} diff --git a/pkg/iac/scanners/terraform/parser/parser.go b/pkg/iac/scanners/terraform/parser/parser.go index 60940d6c6241..695cbee4fb25 100644 --- a/pkg/iac/scanners/terraform/parser/parser.go +++ b/pkg/iac/scanners/terraform/parser/parser.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/hcl/v2/hclparse" "github.com/zclconf/go-cty/cty" + "github.com/aquasecurity/trivy/pkg/fanal/utils" "github.com/aquasecurity/trivy/pkg/iac/ignore" "github.com/aquasecurity/trivy/pkg/iac/terraform" tfcontext "github.com/aquasecurity/trivy/pkg/iac/terraform/context" @@ -47,6 +48,7 @@ type Parser struct { skipCachedModules bool fsMap map[string]fs.FS configsFS fs.FS + skipPaths []string } // New creates a new Parser @@ -78,6 +80,7 @@ func (p *Parser) newModuleParser(moduleFS fs.FS, moduleSource, modulePath, modul mp.moduleName = moduleName mp.logger = log.WithPrefix("terraform parser").With("module", moduleName) mp.projectRoot = p.projectRoot + mp.skipPaths = p.skipPaths p.children = append(p.children, mp) for _, option := range p.options { option(mp) @@ -155,6 +158,10 @@ func (p *Parser) ParseFS(ctx context.Context, dir string) error { if info.IsDir() { continue } + if utils.SkipPath(realPath, utils.CleanSkipPaths(p.skipPaths)) { + p.logger.Debug("Skipping path based on input glob", log.FilePath(realPath), log.Any("glob", p.skipPaths)) + continue + } paths = append(paths, realPath) } sort.Strings(paths) diff --git a/pkg/iac/scanners/terraform/scanner_test.go b/pkg/iac/scanners/terraform/scanner_test.go index 39ee35e81321..a7020b4ddd06 100644 --- a/pkg/iac/scanners/terraform/scanner_test.go +++ b/pkg/iac/scanners/terraform/scanner_test.go @@ -1118,3 +1118,102 @@ func TestSkipDeprecatedGoChecks(t *testing.T) { require.Len(t, results, 1) }) } + +func TestSkipDir(t *testing.T) { + fs := testutil.CreateFS(t, map[string]string{ + "deployments/main.tf": ` +module "use_bad_configuration" { + source = "../modules" +} + +module "use_bad_configuration_2" { + source = "../modules/modules2" +} +`, + "modules/misconfig.tf": `data "aws_iam_policy_document" "bad" { + statement { + actions = [ + "apigateway:*", + ] + + resources = [ + "*", + ] + } +} + +resource "aws_iam_policy" "bad_configuration" { + name_prefix = local.setup_role_name + policy = data.aws_iam_policy_document.bad.json +} +`, + "modules/modules2/misconfig.tf": `data "aws_iam_policy_document" "bad" { + statement { + actions = [ + "apigateway:*", + ] + + resources = [ + "*", + ] + } +} + +resource "aws_iam_policy" "bad_configuration" { + name_prefix = local.setup_role_name + policy = data.aws_iam_policy_document.bad.json +} +`, + }) + + t.Run("use skip-dir option", func(t *testing.T) { + scanner := New( + options.ScannerWithIncludeDeprecatedChecks(true), + ScannerWithSkipDirs([]string{"**/modules/**"}), + ScannerWithAllDirectories(true), + ) + + results, err := scanner.ScanFS(context.TODO(), fs, "deployments") + require.NoError(t, err) + + assert.Empty(t, results) + }) + + t.Run("use skip-files option", func(t *testing.T) { + scanner := New( + options.ScannerWithIncludeDeprecatedChecks(true), + ScannerWithSkipFiles([]string{"**/modules/**/*.tf"}), + ScannerWithAllDirectories(true), + ) + + results, err := scanner.ScanFS(context.TODO(), fs, "deployments") + require.NoError(t, err) + + assert.Empty(t, results) + }) + + t.Run("non existing value for skip-files option", func(t *testing.T) { + scanner := New( + options.ScannerWithIncludeDeprecatedChecks(true), + ScannerWithSkipFiles([]string{"foo/bar*.tf"}), + ScannerWithAllDirectories(true), + ) + + results, err := scanner.ScanFS(context.TODO(), fs, "deployments") + require.NoError(t, err) + + assert.Len(t, results, 4) + }) + + t.Run("empty skip-files option", func(t *testing.T) { + scanner := New( + options.ScannerWithIncludeDeprecatedChecks(true), + ScannerWithAllDirectories(true), + ) + + results, err := scanner.ScanFS(context.TODO(), fs, "deployments") + require.NoError(t, err) + + assert.Len(t, results, 4) + }) +} diff --git a/pkg/misconf/scanner.go b/pkg/misconf/scanner.go index 78f4f4bdb158..7bec3ed6fe14 100644 --- a/pkg/misconf/scanner.go +++ b/pkg/misconf/scanner.go @@ -76,6 +76,8 @@ type ScannerOption struct { ConfigFileSchemas []*ConfigFileSchema DisabledCheckIDs []string + SkipFiles []string + SkipDirs []string } func (o *ScannerOption) Sort() { @@ -297,6 +299,8 @@ func addTFOpts(opts []options.ScannerOption, scannerOption ScannerOption) ([]opt opts = append(opts, terraform.ScannerWithAllDirectories(true), terraform.ScannerWithSkipDownloaded(scannerOption.TfExcludeDownloaded), + terraform.ScannerWithSkipFiles(scannerOption.SkipFiles), + terraform.ScannerWithSkipDirs(scannerOption.SkipDirs), ) return opts, nil From 1faf5297e72f9d4c6047451c79868daa9db5c6e7 Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Wed, 2 Oct 2024 11:04:11 +0400 Subject: [PATCH 27/94] chore: add prefixes to log messages (#7625) Signed-off-by: knqyf263 Co-authored-by: simar7 <1254783+simar7@users.noreply.github.com> --- pkg/commands/artifact/run.go | 18 ++++++++-------- pkg/commands/operation/operation.go | 14 ++++++------- pkg/db/db.go | 19 +++++++++-------- pkg/javadb/client.go | 26 +++++++++++++---------- pkg/k8s/commands/cluster.go | 17 +++++++-------- pkg/log/logger.go | 2 ++ pkg/oci/artifact.go | 8 ++++---- pkg/policy/policy.go | 32 +++++++++++++++-------------- pkg/policy/policy_test.go | 4 ++-- pkg/version/version.go | 4 +++- 10 files changed, 77 insertions(+), 67 deletions(-) diff --git a/pkg/commands/artifact/run.go b/pkg/commands/artifact/run.go index 6f926519b91a..0c9560014a0a 100644 --- a/pkg/commands/artifact/run.go +++ b/pkg/commands/artifact/run.go @@ -470,7 +470,7 @@ func filterMisconfigAnalyzers(included, all []analyzer.Type) ([]analyzer.Type, e return lo.Without(all, included...), nil } -func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.ScanOptions, error) { +func (r *runner) initScannerConfig(ctx context.Context, opts flag.Options) (ScannerConfig, types.ScanOptions, error) { target := opts.Target if opts.Input != "" { target = opts.Input @@ -505,7 +505,7 @@ func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.Scan var configScannerOptions misconf.ScannerOption if opts.Scanners.Enabled(types.MisconfigScanner) || opts.ImageConfigScanners.Enabled(types.MisconfigScanner) { var err error - configScannerOptions, err = initMisconfScannerOption(opts) + configScannerOptions, err = initMisconfScannerOption(ctx, opts) if err != nil { return ScannerConfig{}, types.ScanOptions{}, err } @@ -600,7 +600,7 @@ func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.Scan } func (r *runner) scan(ctx context.Context, opts flag.Options, initializeScanner InitializeScanner) (types.Report, error) { - scannerConfig, scanOptions, err := r.initScannerConfig(opts) + scannerConfig, scanOptions, err := r.initScannerConfig(ctx, opts) if err != nil { return types.Report{}, err } @@ -617,20 +617,20 @@ func (r *runner) scan(ctx context.Context, opts flag.Options, initializeScanner return report, nil } -func initMisconfScannerOption(opts flag.Options) (misconf.ScannerOption, error) { - logger := log.WithPrefix(log.PrefixMisconfiguration) - logger.Info("Misconfiguration scanning is enabled") +func initMisconfScannerOption(ctx context.Context, opts flag.Options) (misconf.ScannerOption, error) { + ctx = log.WithContextPrefix(ctx, log.PrefixMisconfiguration) + log.InfoContext(ctx, "Misconfiguration scanning is enabled") var downloadedPolicyPaths []string var disableEmbedded bool - downloadedPolicyPaths, err := operation.InitBuiltinPolicies(context.Background(), opts.CacheDir, opts.Quiet, opts.SkipCheckUpdate, opts.MisconfOptions.ChecksBundleRepository, opts.RegistryOpts()) + downloadedPolicyPaths, err := operation.InitBuiltinChecks(ctx, opts.CacheDir, opts.Quiet, opts.SkipCheckUpdate, opts.MisconfOptions.ChecksBundleRepository, opts.RegistryOpts()) if err != nil { if !opts.SkipCheckUpdate { - logger.Error("Falling back to embedded checks", log.Err(err)) + log.ErrorContext(ctx, "Falling back to embedded checks", log.Err(err)) } } else { - logger.Debug("Checks successfully loaded from disk") + log.DebugContext(ctx, "Checks successfully loaded from disk") disableEmbedded = true } diff --git a/pkg/commands/operation/operation.go b/pkg/commands/operation/operation.go index 7570c4393b69..ac52eee7fb1e 100644 --- a/pkg/commands/operation/operation.go +++ b/pkg/commands/operation/operation.go @@ -26,7 +26,7 @@ func DownloadDB(ctx context.Context, appVersion, cacheDir string, dbRepositories mu.Lock() defer mu.Unlock() - ctx = log.WithContextPrefix(ctx, "db") + ctx = log.WithContextPrefix(ctx, log.PrefixVulnerabilityDB) dbDir := db.Dir(cacheDir) client := db.NewClient(dbDir, quiet, db.WithDBRepository(dbRepositories)) needsUpdate, err := client.NeedsUpdate(ctx, appVersion, skipUpdate) @@ -77,8 +77,8 @@ func DownloadVEXRepositories(ctx context.Context, opts flag.Options) error { } -// InitBuiltinPolicies downloads the built-in policies and loads them -func InitBuiltinPolicies(ctx context.Context, cacheDir string, quiet, skipUpdate bool, checkBundleRepository string, registryOpts ftypes.RegistryOptions) ([]string, error) { +// InitBuiltinChecks downloads the built-in policies and loads them +func InitBuiltinChecks(ctx context.Context, cacheDir string, quiet, skipUpdate bool, checkBundleRepository string, registryOpts ftypes.RegistryOptions) ([]string, error) { mu.Lock() defer mu.Unlock() @@ -96,14 +96,14 @@ func InitBuiltinPolicies(ctx context.Context, cacheDir string, quiet, skipUpdate } if needsUpdate { - log.Info("Need to update the built-in policies") - log.Info("Downloading the built-in policies...") - if err = client.DownloadBuiltinPolicies(ctx, registryOpts); err != nil { + log.InfoContext(ctx, "Need to update the built-in checks") + log.InfoContext(ctx, "Downloading the built-in checks...") + if err = client.DownloadBuiltinChecks(ctx, registryOpts); err != nil { return nil, xerrors.Errorf("failed to download built-in policies: %w", err) } } - policyPaths, err := client.LoadBuiltinPolicies() + policyPaths, err := client.LoadBuiltinChecks() if err != nil { if skipUpdate { msg := "No downloadable policies were loaded as --skip-check-update is enabled" diff --git a/pkg/db/db.go b/pkg/db/db.go index f7ceb09af4c9..70fbb93a5a91 100644 --- a/pkg/db/db.go +++ b/pkg/db/db.go @@ -93,22 +93,22 @@ func NewClient(dbDir string, quiet bool, opts ...Option) *Client { func (c *Client) NeedsUpdate(ctx context.Context, cliVersion string, skip bool) (bool, error) { meta, err := c.metadata.Get() if err != nil { - log.Debug("There is no valid metadata file", log.Err(err)) + log.DebugContext(ctx, "There is no valid metadata file", log.Err(err)) if skip { - log.Error("The first run cannot skip downloading DB") + log.ErrorContext(ctx, "The first run cannot skip downloading DB") return false, xerrors.New("--skip-update cannot be specified on the first run") } meta = metadata.Metadata{Version: db.SchemaVersion} } if db.SchemaVersion < meta.Version { - log.Error("The Trivy version is old. Update to the latest version.", log.String("version", cliVersion)) + log.ErrorContext(ctx, "Trivy version is old. Update to the latest version.", log.String("version", cliVersion)) return false, xerrors.Errorf("the version of DB schema doesn't match. Local DB: %d, Expected: %d", meta.Version, db.SchemaVersion) } if skip { - log.Debug("Skipping DB update...") + log.DebugContext(ctx, "Skipping DB update...") if err = c.validate(meta); err != nil { return false, xerrors.Errorf("validate error: %w", err) } @@ -116,7 +116,7 @@ func (c *Client) NeedsUpdate(ctx context.Context, cliVersion string, skip bool) } if db.SchemaVersion != meta.Version { - log.Debug("The local DB schema version does not match with supported version schema.", + log.DebugContext(ctx, "The local DB schema version does not match with supported version schema.", log.Int("local_version", meta.Version), log.Int("supported_version", db.SchemaVersion)) return true, nil } @@ -151,7 +151,7 @@ func (c *Client) isNewDB(ctx context.Context, meta metadata.Metadata) bool { func (c *Client) Download(ctx context.Context, dst string, opt types.RegistryOptions) error { // Remove the metadata file under the cache directory before downloading DB if err := c.metadata.Delete(); err != nil { - log.Debug("No metadata file") + log.DebugContext(ctx, "No metadata file") } if err := c.downloadDB(ctx, opt, dst); err != nil { @@ -198,8 +198,11 @@ func (c *Client) initArtifacts(opt types.RegistryOptions) oci.Artifacts { } func (c *Client) downloadDB(ctx context.Context, opt types.RegistryOptions, dst string) error { - log.Info("Downloading vulnerability DB...") - downloadOpt := oci.DownloadOption{MediaType: dbMediaType, Quiet: c.quiet} + log.InfoContext(ctx, "Downloading vulnerability DB...") + downloadOpt := oci.DownloadOption{ + MediaType: dbMediaType, + Quiet: c.quiet, + } if err := c.initArtifacts(opt).Download(ctx, dst, downloadOpt); err != nil { return xerrors.Errorf("failed to download vulnerability DB: %w", err) } diff --git a/pkg/javadb/client.go b/pkg/javadb/client.go index 8c7aa81df9a3..6d5b589bb5d1 100644 --- a/pkg/javadb/client.go +++ b/pkg/javadb/client.go @@ -43,6 +43,7 @@ type Updater struct { } func (u *Updater) Update() error { + ctx := log.WithContextPrefix(context.Background(), log.PrefixJavaDB) metac := db.NewMetadata(u.dbDir) meta, err := metac.Get() @@ -50,15 +51,15 @@ func (u *Updater) Update() error { if !errors.Is(err, os.ErrNotExist) { return xerrors.Errorf("Java DB metadata error: %w", err) } else if u.skip { - log.Error("The first run cannot skip downloading Java DB") + log.ErrorContext(ctx, "The first run cannot skip downloading Java DB") return xerrors.New("'--skip-java-db-update' cannot be specified on the first run") } } - if (meta.Version != SchemaVersion || !u.isNewDB(meta)) && !u.skip { + if (meta.Version != SchemaVersion || !u.isNewDB(ctx, meta)) && !u.skip { // Download DB // TODO: support remote options - if err := u.downloadDB(); err != nil { + if err := u.downloadDB(ctx); err != nil { return xerrors.Errorf("OCI artifact error: %w", err) } @@ -73,33 +74,36 @@ func (u *Updater) Update() error { if err = metac.Update(meta); err != nil { return xerrors.Errorf("Java DB metadata update error: %w", err) } - log.Info("The Java DB is cached for 3 days. If you want to update the database more frequently, " + + log.InfoContext(ctx, "Java DB is cached for 3 days. If you want to update the database more frequently, "+ `"trivy clean --java-db" command clears the DB cache.`) } return nil } -func (u *Updater) isNewDB(meta db.Metadata) bool { +func (u *Updater) isNewDB(ctx context.Context, meta db.Metadata) bool { now := time.Now().UTC() if now.Before(meta.NextUpdate) { - log.Debug("Java DB update was skipped because the local Java DB is the latest") + log.DebugContext(ctx, "Java DB update was skipped because the local Java DB is the latest") return true } if now.Before(meta.DownloadedAt.Add(time.Hour * 24)) { // 1 day - log.Debug("Java DB update was skipped because the local Java DB was downloaded during the last day") + log.DebugContext(ctx, "Java DB update was skipped because the local Java DB was downloaded during the last day") return true } return false } -func (u *Updater) downloadDB() error { - log.Info("Downloading Java DB...") +func (u *Updater) downloadDB(ctx context.Context) error { + log.InfoContext(ctx, "Downloading Java DB...") artifacts := oci.NewArtifacts(u.repos, u.registryOption) - downloadOpt := oci.DownloadOption{MediaType: mediaType, Quiet: u.quiet} - if err := artifacts.Download(context.Background(), u.dbDir, downloadOpt); err != nil { + downloadOpt := oci.DownloadOption{ + MediaType: mediaType, + Quiet: u.quiet, + } + if err := artifacts.Download(ctx, u.dbDir, downloadOpt); err != nil { return xerrors.Errorf("failed to download vulnerability DB: %w", err) } diff --git a/pkg/k8s/commands/cluster.go b/pkg/k8s/commands/cluster.go index 179a089523df..11dd5e0d3a00 100644 --- a/pkg/k8s/commands/cluster.go +++ b/pkg/k8s/commands/cluster.go @@ -37,7 +37,7 @@ func clusterRun(ctx context.Context, opts flag.Options, cluster k8s.Cluster) err trivyk8s.WithExcludeOwned(opts.ExcludeOwned), } if opts.Scanners.AnyEnabled(types.MisconfigScanner) && !opts.DisableNodeCollector { - artifacts, err = trivyk8s.New(cluster, k8sOpts...).ListArtifactAndNodeInfo(ctx, nodeCollectorOptions(opts)...) + artifacts, err = trivyk8s.New(cluster, k8sOpts...).ListArtifactAndNodeInfo(ctx, nodeCollectorOptions(ctx, opts)...) if err != nil { return xerrors.Errorf("get k8s artifacts with node info error: %w", err) } @@ -59,20 +59,17 @@ func clusterRun(ctx context.Context, opts flag.Options, cluster k8s.Cluster) err return runner.run(ctx, artifacts) } -func nodeCollectorOptions(opts flag.Options) []trivyk8s.NodeCollectorOption { +func nodeCollectorOptions(ctx context.Context, opts flag.Options) []trivyk8s.NodeCollectorOption { nodeCollectorOptions := []trivyk8s.NodeCollectorOption{ trivyk8s.WithScanJobNamespace(opts.NodeCollectorNamespace), trivyk8s.WithIgnoreLabels(opts.ExcludeNodes), trivyk8s.WithScanJobImageRef(opts.NodeCollectorImageRef), - trivyk8s.WithTolerations(opts.Tolerations)} - - contentPath, err := operation.InitBuiltinPolicies(context.Background(), - opts.CacheDir, - opts.Quiet, - opts.SkipCheckUpdate, - opts.MisconfOptions.ChecksBundleRepository, - opts.RegistryOpts()) + trivyk8s.WithTolerations(opts.Tolerations), + } + ctx = log.WithContextPrefix(ctx, log.PrefixMisconfiguration) + contentPath, err := operation.InitBuiltinChecks(ctx, opts.CacheDir, opts.Quiet, opts.SkipCheckUpdate, + opts.MisconfOptions.ChecksBundleRepository, opts.RegistryOpts()) if err != nil { log.Error("Falling back to embedded checks", log.Err(err)) nodeCollectorOptions = append(nodeCollectorOptions, diff --git a/pkg/log/logger.go b/pkg/log/logger.go index ac629d211157..2948886b9559 100644 --- a/pkg/log/logger.go +++ b/pkg/log/logger.go @@ -23,6 +23,8 @@ const ( PrefixMisconfiguration = "misconfig" PrefixSecret = "secret" PrefixLicense = "license" + PrefixVulnerabilityDB = "vulndb" + PrefixJavaDB = "javadb" ) // Logger is an alias of slog.Logger diff --git a/pkg/oci/artifact.go b/pkg/oci/artifact.go index 345149892a4e..416952578918 100644 --- a/pkg/oci/artifact.go +++ b/pkg/oci/artifact.go @@ -225,19 +225,19 @@ func NewArtifacts(repos []name.Reference, opt types.RegistryOptions, opts ...Opt // Attempts to download next artifact if the first one fails due to a temporary error. func (a Artifacts) Download(ctx context.Context, dst string, opt DownloadOption) error { for i, art := range a { - log.Info("Downloading artifact...", log.String("repo", art.repository)) + log.InfoContext(ctx, "Downloading artifact...", log.String("repo", art.repository)) err := art.Download(ctx, dst, opt) if err == nil { - log.Info("Artifact successfully downloaded", log.String("repo", art.repository)) + log.InfoContext(ctx, "Artifact successfully downloaded", log.String("repo", art.repository)) return nil } if !shouldTryOtherRepo(err) { return xerrors.Errorf("failed to download artifact from %s: %w", art.repository, err) } - log.Error("Failed to download artifact", log.String("repo", art.repository), log.Err(err)) + log.ErrorContext(ctx, "Failed to download artifact", log.String("repo", art.repository), log.Err(err)) if i < len(a)-1 { - log.Info("Trying to download artifact from other repository...") + log.InfoContext(ctx, "Trying to download artifact from other repository...") } } diff --git a/pkg/policy/policy.go b/pkg/policy/policy.go index 2dbe2fc1b89a..e277936829c5 100644 --- a/pkg/policy/policy.go +++ b/pkg/policy/policy.go @@ -89,20 +89,22 @@ func NewClient(cacheDir string, quiet bool, checkBundleRepo string, opts ...Opti }, nil } -func (c *Client) populateOCIArtifact(registryOpts types.RegistryOptions) { +func (c *Client) populateOCIArtifact(ctx context.Context, registryOpts types.RegistryOptions) { if c.artifact == nil { - log.Debug("Loading check bundle", log.String("repository", c.checkBundleRepo)) + log.DebugContext(ctx, "Loading check bundle", log.String("repository", c.checkBundleRepo)) c.artifact = oci.NewArtifact(c.checkBundleRepo, registryOpts) } } -// DownloadBuiltinPolicies download default policies from GitHub Pages -func (c *Client) DownloadBuiltinPolicies(ctx context.Context, registryOpts types.RegistryOptions) error { - c.populateOCIArtifact(registryOpts) +// DownloadBuiltinChecks download default policies from GitHub Pages +func (c *Client) DownloadBuiltinChecks(ctx context.Context, registryOpts types.RegistryOptions) error { + c.populateOCIArtifact(ctx, registryOpts) dst := c.contentDir() - if err := c.artifact.Download(ctx, dst, - oci.DownloadOption{MediaType: policyMediaType, Quiet: c.quiet}, + if err := c.artifact.Download(ctx, dst, oci.DownloadOption{ + MediaType: policyMediaType, + Quiet: c.quiet, + }, ); err != nil { return xerrors.Errorf("download error: %w", err) } @@ -111,7 +113,7 @@ func (c *Client) DownloadBuiltinPolicies(ctx context.Context, registryOpts types if err != nil { return xerrors.Errorf("digest error: %w", err) } - log.Debug("Digest of the built-in policies", log.String("digest", digest)) + log.DebugContext(ctx, "Digest of the built-in checks", log.String("digest", digest)) // Update metadata.json with the new digest and the current date if err = c.updateMetadata(digest, c.clock.Now()); err != nil { @@ -121,8 +123,8 @@ func (c *Client) DownloadBuiltinPolicies(ctx context.Context, registryOpts types return nil } -// LoadBuiltinPolicies loads default policies -func (c *Client) LoadBuiltinPolicies() ([]string, error) { +// LoadBuiltinChecks loads default policies +func (c *Client) LoadBuiltinChecks() ([]string, error) { f, err := os.Open(c.manifestPath()) if err != nil { return nil, xerrors.Errorf("manifest file open error (%s): %w", c.manifestPath(), err) @@ -150,7 +152,7 @@ func (c *Client) LoadBuiltinPolicies() ([]string, error) { // NeedsUpdate returns if the default check should be updated func (c *Client) NeedsUpdate(ctx context.Context, registryOpts types.RegistryOptions) (bool, error) { - meta, err := c.GetMetadata() + meta, err := c.GetMetadata(ctx) if err != nil { return true, nil } @@ -160,7 +162,7 @@ func (c *Client) NeedsUpdate(ctx context.Context, registryOpts types.RegistryOpt return false, nil } - c.populateOCIArtifact(registryOpts) + c.populateOCIArtifact(ctx, registryOpts) digest, err := c.artifact.Digest(ctx) if err != nil { return false, xerrors.Errorf("digest error: %w", err) @@ -211,17 +213,17 @@ func (c *Client) updateMetadata(digest string, now time.Time) error { return nil } -func (c *Client) GetMetadata() (*Metadata, error) { +func (c *Client) GetMetadata(ctx context.Context) (*Metadata, error) { f, err := os.Open(c.metadataPath()) if err != nil { - log.Debug("Failed to open the check metadata", log.Err(err)) + log.DebugContext(ctx, "Failed to open the check metadata", log.Err(err)) return nil, err } defer f.Close() var meta Metadata if err = json.NewDecoder(f).Decode(&meta); err != nil { - log.Warn("Check metadata decode error", log.Err(err)) + log.WarnContext(ctx, "Check metadata decode error", log.Err(err)) return nil, err } diff --git a/pkg/policy/policy_test.go b/pkg/policy/policy_test.go index f6875eb1c9cb..4752fa4ce7fc 100644 --- a/pkg/policy/policy_test.go +++ b/pkg/policy/policy_test.go @@ -120,7 +120,7 @@ func TestClient_LoadBuiltinPolicies(t *testing.T) { c, err := policy.NewClient(tt.cacheDir, true, "", policy.WithOCIArtifact(art)) require.NoError(t, err) - got, err := c.LoadBuiltinPolicies() + got, err := c.LoadBuiltinChecks() if tt.wantErr != "" { require.Error(t, err) assert.Contains(t, err.Error(), tt.wantErr) @@ -361,7 +361,7 @@ func TestClient_DownloadBuiltinPolicies(t *testing.T) { c, err := policy.NewClient(tempDir, true, "", policy.WithClock(tt.clock), policy.WithOCIArtifact(art)) require.NoError(t, err) - err = c.DownloadBuiltinPolicies(context.Background(), ftypes.RegistryOptions{}) + err = c.DownloadBuiltinChecks(context.Background(), ftypes.RegistryOptions{}) if tt.wantErr != "" { require.Error(t, err) assert.Contains(t, err.Error(), tt.wantErr) diff --git a/pkg/version/version.go b/pkg/version/version.go index 60ee62bd52f1..17da77a2a1bd 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -1,6 +1,7 @@ package version import ( + "context" "fmt" "path/filepath" @@ -80,7 +81,8 @@ func NewVersionInfo(cacheDir string) VersionInfo { log.Debug("Failed to instantiate policy client", log.Err(err)) } if pc != nil && err == nil { - pbMetaRaw, err := pc.GetMetadata() + ctx := log.WithContextPrefix(context.TODO(), log.PrefixMisconfiguration) + pbMetaRaw, err := pc.GetMetadata(ctx) if err != nil { log.Debug("Failed to get policy metadata", log.Err(err)) From 82e2adc6f8e68d0cc0021031170c2adb60d213ba Mon Sep 17 00:00:00 2001 From: simar7 <1254783+simar7@users.noreply.github.com> Date: Wed, 2 Oct 2024 01:49:08 -0600 Subject: [PATCH 28/94] fix(misconf): Disable deprecated checks by default (#7632) --- docs/docs/references/configuration/cli/trivy_config.md | 2 +- docs/docs/references/configuration/cli/trivy_filesystem.md | 2 +- docs/docs/references/configuration/cli/trivy_image.md | 2 +- docs/docs/references/configuration/cli/trivy_kubernetes.md | 2 +- docs/docs/references/configuration/cli/trivy_repository.md | 2 +- docs/docs/references/configuration/cli/trivy_rootfs.md | 2 +- docs/docs/references/configuration/config-file.md | 2 +- pkg/flag/rego_flags.go | 1 - 8 files changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/docs/references/configuration/cli/trivy_config.md b/docs/docs/references/configuration/cli/trivy_config.md index 91cd64292ea8..b32e74c1c752 100644 --- a/docs/docs/references/configuration/cli/trivy_config.md +++ b/docs/docs/references/configuration/cli/trivy_config.md @@ -31,7 +31,7 @@ trivy config [flags] DIR -h, --help help for config --ignore-policy string specify the Rego file path to evaluate each vulnerability --ignorefile string specify .trivyignore file (default ".trivyignore") - --include-deprecated-checks include deprecated checks (default true) + --include-deprecated-checks include deprecated checks --include-non-failures include successes and exceptions, available with '--scanners misconfig' --k8s-version string specify k8s version to validate outdated api by it (example: 1.21.0) --misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot]) diff --git a/docs/docs/references/configuration/cli/trivy_filesystem.md b/docs/docs/references/configuration/cli/trivy_filesystem.md index 9944a2d618ff..620c43808e91 100644 --- a/docs/docs/references/configuration/cli/trivy_filesystem.md +++ b/docs/docs/references/configuration/cli/trivy_filesystem.md @@ -53,7 +53,7 @@ trivy filesystem [flags] PATH --ignore-unfixed display only fixed vulnerabilities --ignored-licenses strings specify a list of license to ignore --ignorefile string specify .trivyignore file (default ".trivyignore") - --include-deprecated-checks include deprecated checks (default true) + --include-deprecated-checks include deprecated checks --include-dev-deps include development dependencies in the report (supported: npm, yarn) --include-non-failures include successes and exceptions, available with '--scanners misconfig' --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) diff --git a/docs/docs/references/configuration/cli/trivy_image.md b/docs/docs/references/configuration/cli/trivy_image.md index b63daffbf4ad..cd00214793e6 100644 --- a/docs/docs/references/configuration/cli/trivy_image.md +++ b/docs/docs/references/configuration/cli/trivy_image.md @@ -71,7 +71,7 @@ trivy image [flags] IMAGE_NAME --ignorefile string specify .trivyignore file (default ".trivyignore") --image-config-scanners strings comma-separated list of what security issues to detect on container image configurations (misconfig,secret) --image-src strings image source(s) to use, in priority order (docker,containerd,podman,remote) (default [docker,containerd,podman,remote]) - --include-deprecated-checks include deprecated checks (default true) + --include-deprecated-checks include deprecated checks --include-non-failures include successes and exceptions, available with '--scanners misconfig' --input string input file path instead of image name --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) diff --git a/docs/docs/references/configuration/cli/trivy_kubernetes.md b/docs/docs/references/configuration/cli/trivy_kubernetes.md index 35190b1b82b5..8cec25ec3cba 100644 --- a/docs/docs/references/configuration/cli/trivy_kubernetes.md +++ b/docs/docs/references/configuration/cli/trivy_kubernetes.md @@ -66,7 +66,7 @@ trivy kubernetes [flags] [CONTEXT] --ignore-unfixed display only fixed vulnerabilities --ignorefile string specify .trivyignore file (default ".trivyignore") --image-src strings image source(s) to use, in priority order (docker,containerd,podman,remote) (default [docker,containerd,podman,remote]) - --include-deprecated-checks include deprecated checks (default true) + --include-deprecated-checks include deprecated checks --include-kinds strings indicate the kinds included in scanning (example: node) --include-namespaces strings indicate the namespaces included in scanning (example: kube-system) --include-non-failures include successes and exceptions, available with '--scanners misconfig' diff --git a/docs/docs/references/configuration/cli/trivy_repository.md b/docs/docs/references/configuration/cli/trivy_repository.md index 59e4f2c08cb0..959bf9a8086f 100644 --- a/docs/docs/references/configuration/cli/trivy_repository.md +++ b/docs/docs/references/configuration/cli/trivy_repository.md @@ -53,7 +53,7 @@ trivy repository [flags] (REPO_PATH | REPO_URL) --ignore-unfixed display only fixed vulnerabilities --ignored-licenses strings specify a list of license to ignore --ignorefile string specify .trivyignore file (default ".trivyignore") - --include-deprecated-checks include deprecated checks (default true) + --include-deprecated-checks include deprecated checks --include-dev-deps include development dependencies in the report (supported: npm, yarn) --include-non-failures include successes and exceptions, available with '--scanners misconfig' --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) diff --git a/docs/docs/references/configuration/cli/trivy_rootfs.md b/docs/docs/references/configuration/cli/trivy_rootfs.md index 6022f4589446..277634ed62a9 100644 --- a/docs/docs/references/configuration/cli/trivy_rootfs.md +++ b/docs/docs/references/configuration/cli/trivy_rootfs.md @@ -56,7 +56,7 @@ trivy rootfs [flags] ROOTDIR --ignore-unfixed display only fixed vulnerabilities --ignored-licenses strings specify a list of license to ignore --ignorefile string specify .trivyignore file (default ".trivyignore") - --include-deprecated-checks include deprecated checks (default true) + --include-deprecated-checks include deprecated checks --include-non-failures include successes and exceptions, available with '--scanners misconfig' --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --license-confidence-level float specify license classifier's confidence level (default 0.9) diff --git a/docs/docs/references/configuration/config-file.md b/docs/docs/references/configuration/config-file.md index ae3a017fda05..21d327c301b7 100644 --- a/docs/docs/references/configuration/config-file.md +++ b/docs/docs/references/configuration/config-file.md @@ -479,7 +479,7 @@ rego: data: [] # Same as '--include-deprecated-checks' - include-deprecated-checks: true + include-deprecated-checks: false # Same as '--check-namespaces' namespaces: [] diff --git a/pkg/flag/rego_flags.go b/pkg/flag/rego_flags.go index 5e856f30062e..4b291f0a5eb3 100644 --- a/pkg/flag/rego_flags.go +++ b/pkg/flag/rego_flags.go @@ -11,7 +11,6 @@ var ( Name: "include-deprecated-checks", ConfigName: "rego.include-deprecated-checks", Usage: "include deprecated checks", - Default: true, } SkipCheckUpdateFlag = Flag[bool]{ Name: "skip-check-update", From 8735242b8fb7c45039c74cf9d9d6111814515740 Mon Sep 17 00:00:00 2001 From: simar7 <1254783+simar7@users.noreply.github.com> Date: Wed, 2 Oct 2024 01:51:30 -0600 Subject: [PATCH 29/94] chore(deps): Bump trivy-checks to v1.1.0 (#7631) --- docs/docs/references/configuration/cli/trivy_config.md | 2 +- docs/docs/references/configuration/cli/trivy_filesystem.md | 2 +- docs/docs/references/configuration/cli/trivy_image.md | 2 +- docs/docs/references/configuration/cli/trivy_kubernetes.md | 2 +- docs/docs/references/configuration/cli/trivy_repository.md | 2 +- docs/docs/references/configuration/cli/trivy_rootfs.md | 2 +- docs/docs/references/configuration/cli/trivy_vm.md | 2 +- docs/docs/references/configuration/config-file.md | 2 +- go.mod | 2 +- go.sum | 4 ++-- pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go | 2 +- pkg/policy/policy.go | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/docs/references/configuration/cli/trivy_config.md b/docs/docs/references/configuration/cli/trivy_config.md index b32e74c1c752..be7854548496 100644 --- a/docs/docs/references/configuration/cli/trivy_config.md +++ b/docs/docs/references/configuration/cli/trivy_config.md @@ -13,7 +13,7 @@ trivy config [flags] DIR --cache-ttl duration cache TTL when using redis as cache backend --cf-params strings specify paths to override the CloudFormation parameters files --check-namespaces strings Rego namespaces - --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") + --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:1") --compliance string compliance report to generate --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-data strings specify paths from which data for the Rego checks will be recursively loaded diff --git a/docs/docs/references/configuration/cli/trivy_filesystem.md b/docs/docs/references/configuration/cli/trivy_filesystem.md index 620c43808e91..0abec4990173 100644 --- a/docs/docs/references/configuration/cli/trivy_filesystem.md +++ b/docs/docs/references/configuration/cli/trivy_filesystem.md @@ -23,7 +23,7 @@ trivy filesystem [flags] PATH --cache-ttl duration cache TTL when using redis as cache backend --cf-params strings specify paths to override the CloudFormation parameters files --check-namespaces strings Rego namespaces - --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") + --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:1") --compliance string compliance report to generate --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-data strings specify paths from which data for the Rego checks will be recursively loaded diff --git a/docs/docs/references/configuration/cli/trivy_image.md b/docs/docs/references/configuration/cli/trivy_image.md index cd00214793e6..f9095f041572 100644 --- a/docs/docs/references/configuration/cli/trivy_image.md +++ b/docs/docs/references/configuration/cli/trivy_image.md @@ -37,7 +37,7 @@ trivy image [flags] IMAGE_NAME --cache-backend string [EXPERIMENTAL] cache backend (e.g. redis://localhost:6379) (default "fs") --cache-ttl duration cache TTL when using redis as cache backend --check-namespaces strings Rego namespaces - --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") + --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:1") --compliance string compliance report to generate (docker-cis-1.6.0) --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-data strings specify paths from which data for the Rego checks will be recursively loaded diff --git a/docs/docs/references/configuration/cli/trivy_kubernetes.md b/docs/docs/references/configuration/cli/trivy_kubernetes.md index 8cec25ec3cba..99fbc1badaa2 100644 --- a/docs/docs/references/configuration/cli/trivy_kubernetes.md +++ b/docs/docs/references/configuration/cli/trivy_kubernetes.md @@ -33,7 +33,7 @@ trivy kubernetes [flags] [CONTEXT] --cache-backend string [EXPERIMENTAL] cache backend (e.g. redis://localhost:6379) (default "fs") --cache-ttl duration cache TTL when using redis as cache backend --check-namespaces strings Rego namespaces - --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") + --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:1") --compliance string compliance report to generate (k8s-nsa-1.0,k8s-cis-1.23,eks-cis-1.4,rke2-cis-1.24,k8s-pss-baseline-0.1,k8s-pss-restricted-0.1) --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-data strings specify paths from which data for the Rego checks will be recursively loaded diff --git a/docs/docs/references/configuration/cli/trivy_repository.md b/docs/docs/references/configuration/cli/trivy_repository.md index 959bf9a8086f..821923262dee 100644 --- a/docs/docs/references/configuration/cli/trivy_repository.md +++ b/docs/docs/references/configuration/cli/trivy_repository.md @@ -23,7 +23,7 @@ trivy repository [flags] (REPO_PATH | REPO_URL) --cache-ttl duration cache TTL when using redis as cache backend --cf-params strings specify paths to override the CloudFormation parameters files --check-namespaces strings Rego namespaces - --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") + --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:1") --commit string pass the commit hash to be scanned --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-data strings specify paths from which data for the Rego checks will be recursively loaded diff --git a/docs/docs/references/configuration/cli/trivy_rootfs.md b/docs/docs/references/configuration/cli/trivy_rootfs.md index 277634ed62a9..bf2575af23b9 100644 --- a/docs/docs/references/configuration/cli/trivy_rootfs.md +++ b/docs/docs/references/configuration/cli/trivy_rootfs.md @@ -26,7 +26,7 @@ trivy rootfs [flags] ROOTDIR --cache-ttl duration cache TTL when using redis as cache backend --cf-params strings specify paths to override the CloudFormation parameters files --check-namespaces strings Rego namespaces - --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") + --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:1") --config-check strings specify the paths to the Rego check files or to the directories containing them, applying config files --config-data strings specify paths from which data for the Rego checks will be recursively loaded --config-file-schemas strings specify paths to JSON configuration file schemas to determine that a file matches some configuration and pass the schema to Rego checks for type checking diff --git a/docs/docs/references/configuration/cli/trivy_vm.md b/docs/docs/references/configuration/cli/trivy_vm.md index 9b7f6a6fef43..14ce8b78c21a 100644 --- a/docs/docs/references/configuration/cli/trivy_vm.md +++ b/docs/docs/references/configuration/cli/trivy_vm.md @@ -23,7 +23,7 @@ trivy vm [flags] VM_IMAGE --aws-region string AWS region to scan --cache-backend string [EXPERIMENTAL] cache backend (e.g. redis://localhost:6379) (default "fs") --cache-ttl duration cache TTL when using redis as cache backend - --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:0") + --checks-bundle-repository string OCI registry URL to retrieve checks bundle from (default "ghcr.io/aquasecurity/trivy-checks:1") --compliance string compliance report to generate --config-file-schemas strings specify paths to JSON configuration file schemas to determine that a file matches some configuration and pass the schema to Rego checks for type checking --custom-headers strings custom headers in client mode diff --git a/docs/docs/references/configuration/config-file.md b/docs/docs/references/configuration/config-file.md index 21d327c301b7..9bc9d4351360 100644 --- a/docs/docs/references/configuration/config-file.md +++ b/docs/docs/references/configuration/config-file.md @@ -373,7 +373,7 @@ license: ```yaml misconfiguration: # Same as '--checks-bundle-repository' - checks-bundle-repository: "ghcr.io/aquasecurity/trivy-checks:0" + checks-bundle-repository: "ghcr.io/aquasecurity/trivy-checks:1" cloudformation: # Same as '--cf-params' diff --git a/go.mod b/go.mod index 8f5e151e6ef4..d0d10457d81c 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/aquasecurity/table v1.8.0 github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8 github.com/aquasecurity/tml v0.6.1 - github.com/aquasecurity/trivy-checks v0.13.1-0.20240830230553-53ddbbade784 + github.com/aquasecurity/trivy-checks v1.1.0 github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1 github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240707095038-0300bc49b68b diff --git a/go.sum b/go.sum index b284e23f5722..eafeea1e389b 100644 --- a/go.sum +++ b/go.sum @@ -347,8 +347,8 @@ github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8 h1:b43UVqY github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8/go.mod h1:wXA9k3uuaxY3yu7gxrxZDPo/04FEMJtwyecdAlYrEIo= github.com/aquasecurity/tml v0.6.1 h1:y2ZlGSfrhnn7t4ZJ/0rotuH+v5Jgv6BDDO5jB6A9gwo= github.com/aquasecurity/tml v0.6.1/go.mod h1:OnYMWY5lvI9ejU7yH9LCberWaaTBW7hBFsITiIMY2yY= -github.com/aquasecurity/trivy-checks v0.13.1-0.20240830230553-53ddbbade784 h1:1rvPiCK8uQd3sarOuZ60nwksHpxsNdrvptz4eDW/V14= -github.com/aquasecurity/trivy-checks v0.13.1-0.20240830230553-53ddbbade784/go.mod h1:Ralz7PWmR3LirHlXxVtUXc+7CFmWE82jbLk7+TPvV/0= +github.com/aquasecurity/trivy-checks v1.1.0 h1:I0tVOK8dG/KHrWsqfGNYp2uD/i0f+yS7Je31F+LIUqQ= +github.com/aquasecurity/trivy-checks v1.1.0/go.mod h1:tVzhU0gajD3GmxKPLn/BHR8ZeUquc5ajQTmAsi0kCCU= github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1 h1:G0gnacAORRUqz2Tm5MqivSpldY2GZ74ijhJcMsae+sA= github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1/go.mod h1:PYkSRx4dlgFATEt+okGwibvbxVEtqsOdH+vX/saACYE= github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 h1:JVgBIuIYbwG+ekC5lUHUpGJboPYiCcxiz06RCtz8neI= diff --git a/pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go b/pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go index 1c0ac8234862..d70280da437f 100644 --- a/pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go +++ b/pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go @@ -34,6 +34,6 @@ func Test_Scanning_Plan(t *testing.T) { } } - assert.Len(t, failedResults, 9) + assert.Len(t, failedResults, 8) } diff --git a/pkg/policy/policy.go b/pkg/policy/policy.go index e277936829c5..670588868dcb 100644 --- a/pkg/policy/policy.go +++ b/pkg/policy/policy.go @@ -18,7 +18,7 @@ import ( ) const ( - BundleVersion = 0 // Latest released MAJOR version for trivy-checks + BundleVersion = 1 // Latest released MAJOR version for trivy-checks BundleRepository = "ghcr.io/aquasecurity/trivy-checks" policyMediaType = "application/vnd.cncf.openpolicyagent.layer.v1.tar+gzip" updateInterval = 24 * time.Hour From 3e1fa2100074e840bacdd65947425b08750b7d9a Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 2 Oct 2024 12:06:14 +0200 Subject: [PATCH 30/94] fix(secret): change grafana token regex to find them without unquoted (#7627) --- pkg/fanal/secret/builtin-rules.go | 2 +- pkg/fanal/secret/scanner_test.go | 74 +++++++++++++++++++++++ pkg/fanal/secret/testdata/grafana-env.txt | 2 + 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 pkg/fanal/secret/testdata/grafana-env.txt diff --git a/pkg/fanal/secret/builtin-rules.go b/pkg/fanal/secret/builtin-rules.go index a83d8eba35ba..09bf98fd3da8 100644 --- a/pkg/fanal/secret/builtin-rules.go +++ b/pkg/fanal/secret/builtin-rules.go @@ -553,7 +553,7 @@ var builtinRules = []Rule{ Category: CategoryGrafana, Title: "Grafana API token", Severity: "MEDIUM", - Regex: MustCompile(`['\"]eyJrIjoi(?i)[a-z0-9\-_=]{72,92}['\"]`), + Regex: MustCompile(`['\"]?eyJrIjoi(?i)[a-z0-9\-_=]{72,92}['\"]?`), Keywords: []string{"eyJrIjoi"}, }, { diff --git a/pkg/fanal/secret/scanner_test.go b/pkg/fanal/secret/scanner_test.go index 44b5a2458e79..f17b1150dd4a 100644 --- a/pkg/fanal/secret/scanner_test.go +++ b/pkg/fanal/secret/scanner_test.go @@ -690,6 +690,71 @@ func TestSecretScanner(t *testing.T) { }, } + wantFindingGrafanaQuoted := types.SecretFinding{ + RuleID: "grafana-api-token", + Category: secret.CategoryGrafana, + Title: "Grafana API token", + Severity: "MEDIUM", + StartLine: 1, + EndLine: 1, + Match: "GRAFANA_TOKEN=**********************************************************************************************", + Code: types.Code{ + Lines: []types.Line{ + { + Number: 1, + Content: "GRAFANA_TOKEN=**********************************************************************************************", + Highlighted: "GRAFANA_TOKEN=**********************************************************************************************", + IsCause: true, + FirstCause: true, + LastCause: true, + }, + { + Number: 2, + Content: "GRAFANA_TOKEN=**************************************************************************************", + Highlighted: "GRAFANA_TOKEN=**************************************************************************************", + IsCause: false, + FirstCause: false, + LastCause: false, + }, + }, + }, + } + + wantFindingGrafanaUnquoted := types.SecretFinding{ + RuleID: "grafana-api-token", + Category: secret.CategoryGrafana, + Title: "Grafana API token", + Severity: "MEDIUM", + StartLine: 2, + EndLine: 2, + Match: "GRAFANA_TOKEN=********************************************************************************************", + Code: types.Code{ + Lines: []types.Line{ + { + Number: 1, + Content: "GRAFANA_TOKEN=**************************************************************************************", + Highlighted: "GRAFANA_TOKEN=**************************************************************************************", + IsCause: false, + FirstCause: false, + LastCause: false, + }, + { + Number: 2, + Content: "GRAFANA_TOKEN=********************************************************************************************", + Highlighted: "GRAFANA_TOKEN=********************************************************************************************", + IsCause: true, + FirstCause: true, + LastCause: true, + }, + { + Number: 3, + Content: "", + Highlighted: "", + }, + }, + }, + } + wantMultiLine := types.SecretFinding{ RuleID: "multi-line-secret", Category: "general", @@ -858,6 +923,15 @@ func TestSecretScanner(t *testing.T) { Findings: []types.SecretFinding{wantFindingHuggingFace}, }, }, + { + name: "find grafana secret", + configPath: filepath.Join("testdata", "config.yaml"), + inputFilePath: filepath.Join("testdata", "grafana-env.txt"), + want: types.Secret{ + FilePath: filepath.Join("testdata", "grafana-env.txt"), + Findings: []types.SecretFinding{wantFindingGrafanaUnquoted, wantFindingGrafanaQuoted}, + }, + }, { name: "find JWT token", configPath: filepath.Join("testdata", "config.yaml"), diff --git a/pkg/fanal/secret/testdata/grafana-env.txt b/pkg/fanal/secret/testdata/grafana-env.txt new file mode 100644 index 000000000000..ede29f880a6b --- /dev/null +++ b/pkg/fanal/secret/testdata/grafana-env.txt @@ -0,0 +1,2 @@ +GRAFANA_TOKEN="eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbkT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk" +GRAFANA_TOKEN=eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbkT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk From 69bf7e00ea5ab483692db830fdded26a31f03183 Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Wed, 2 Oct 2024 15:44:17 +0400 Subject: [PATCH 31/94] feat: support RPM archives (#7628) Signed-off-by: knqyf263 --- .gitignore | 3 + docs/docs/coverage/os/index.md | 4 +- docs/docs/coverage/{os => others}/bitnami.md | 4 +- docs/docs/coverage/{os => others}/conda.md | 0 docs/docs/coverage/others/rpm.md | 42 +++++ docs/docs/supply-chain/sbom.md | 2 +- go.mod | 7 +- go.sum | 14 +- magefiles/magefile.go | 4 +- mkdocs.yml | 6 +- pkg/commands/artifact/run.go | 7 + pkg/fanal/analyzer/const.go | 1 + pkg/fanal/analyzer/pkg/rpm/archive.go | 161 ++++++++++++++++++ pkg/fanal/analyzer/pkg/rpm/archive_test.go | 81 +++++++++ .../analyzer/pkg/rpm/testdata/fixture.go | 63 +++++++ pkg/fanal/applier/docker.go | 2 +- 16 files changed, 386 insertions(+), 15 deletions(-) rename docs/docs/coverage/{os => others}/bitnami.md (95%) rename docs/docs/coverage/{os => others}/conda.md (100%) create mode 100644 docs/docs/coverage/others/rpm.md create mode 100644 pkg/fanal/analyzer/pkg/rpm/archive.go create mode 100644 pkg/fanal/analyzer/pkg/rpm/archive_test.go create mode 100644 pkg/fanal/analyzer/pkg/rpm/testdata/fixture.go diff --git a/.gitignore b/.gitignore index 94254d6b0319..88070261a647 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ dist # Signing gpg.key cmd/trivy/trivy + +# RPM +*.rpm diff --git a/docs/docs/coverage/os/index.md b/docs/docs/coverage/os/index.md index a49793db8124..8756ddc8aa95 100644 --- a/docs/docs/coverage/os/index.md +++ b/docs/docs/coverage/os/index.md @@ -28,14 +28,14 @@ Trivy supports operating systems for | [Photon OS](photon.md) | 1.0, 2.0, 3.0, 4.0 | tndf/yum/rpm | | [Debian GNU/Linux](debian.md) | 7, 8, 9, 10, 11, 12 | apt/dpkg | | [Ubuntu](ubuntu.md) | All versions supported by Canonical | apt/dpkg | -| [OSs with installed Conda](conda.md) | - | conda | +| [OSs with installed Conda](../others/conda.md) | - | conda | ## Supported container images | Container image | Supported Versions | Package Managers | |-----------------------------------------------|-------------------------------------|------------------| | [Google Distroless](google-distroless.md)[^2] | Any | apt/dpkg | -| [Bitnami](bitnami.md) | Any | - | +| [Bitnami](../others/bitnami.md) | Any | - | Each page gives more details. diff --git a/docs/docs/coverage/os/bitnami.md b/docs/docs/coverage/others/bitnami.md similarity index 95% rename from docs/docs/coverage/os/bitnami.md rename to docs/docs/coverage/others/bitnami.md index 56cfb97a4601..4773fd9ab20c 100644 --- a/docs/docs/coverage/os/bitnami.md +++ b/docs/docs/coverage/others/bitnami.md @@ -4,8 +4,8 @@ Scanning results may be inaccurate. While it is not an OS, this page describes the details of the [container images provided by Bitnami](https://github.com/bitnami/containers). -Bitnami images are based on [Debian](debian.md). -Please see [the Debian page](debian.md) for OS packages. +Bitnami images are based on [Debian](../os/debian.md). +Please see [the Debian page](../os/debian.md) for OS packages. Trivy supports the following scanners for Bitnami packages. diff --git a/docs/docs/coverage/os/conda.md b/docs/docs/coverage/others/conda.md similarity index 100% rename from docs/docs/coverage/os/conda.md rename to docs/docs/coverage/others/conda.md diff --git a/docs/docs/coverage/others/rpm.md b/docs/docs/coverage/others/rpm.md new file mode 100644 index 000000000000..092cd4396b07 --- /dev/null +++ b/docs/docs/coverage/others/rpm.md @@ -0,0 +1,42 @@ +# RPM Archives + +!!! warning "EXPERIMENTAL" + This feature might change without preserving backwards compatibility. + +Trivy supports the following scanners for RPM archives. + +| Scanner | Supported | +|:-------------:|:---------:| +| SBOM | ✓ | +| Vulnerability | ✓[^1] | +| License | ✓ | + +The table below outlines the features offered by Trivy. + +## SBOM +Trivy analyzes RPM archives matching `*.rpm`. +This feature is currently disabled by default but can be enabled with an environment variable, `TRIVY_EXPERIMENTAL_RPM_ARCHIVE`. + +```shell +TRIVY_EXPERIMENTAL_RPM_ARCHIVE=true trivy fs ./rpms --format cyclonedx --output rpms.cdx.json +``` + +!!! note + Currently, it works with `--format cyclonedx`, `--format spdx` or `--format spdx-json`. + + +## Vulnerability +Since RPM files don't have OS information, you need to generate SBOM, fill in the OS information manually and then scan the SBOM for vulnerabilities. + +For example: + +```shell +$ TRIVY_EXPERIMENTAL_RPM_ARCHIVE=true trivy fs ./rpms -f cyclonedx -o rpms.cdx.json +$ jq '(.components[] | select(.type == "operating-system")) |= (.name = "redhat" | .version = "7.9")' rpms.cdx.json > rpms-res.cdx.json +$ trivy sbom ./rpms-res.cdx.json +``` + +## License +If licenses are included in the RPM archive, Trivy extracts it. + +[^1]: Need to generate SBOM first and add OS information to that SBOM diff --git a/docs/docs/supply-chain/sbom.md b/docs/docs/supply-chain/sbom.md index ed57195b3550..f2f2d55c79a5 100644 --- a/docs/docs/supply-chain/sbom.md +++ b/docs/docs/supply-chain/sbom.md @@ -743,7 +743,7 @@ Trivy searches for SBOM files in container images with the following extensions: - `.cdx` - `.cdx.json` -In addition, Trivy automatically detects SBOM files in [Bitnami images](https://github.com/bitnami/containers), [see here](../coverage/os/bitnami.md) for more details. +In addition, Trivy automatically detects SBOM files in [Bitnami images](https://github.com/bitnami/containers), [see here](../coverage/others/bitnami.md) for more details. It is enabled in the following targets. diff --git a/go.mod b/go.mod index d0d10457d81c..d01ce2a7d4c7 100644 --- a/go.mod +++ b/go.mod @@ -98,6 +98,7 @@ require ( github.com/package-url/packageurl-go v0.1.3 github.com/quasilyte/go-ruleguard/dsl v0.3.22 github.com/samber/lo v1.47.0 + github.com/sassoftware/go-rpmutils v0.4.0 github.com/secure-systems-lab/go-securesystemslib v0.8.0 github.com/sigstore/rekor v1.3.6 github.com/sirupsen/logrus v1.9.3 @@ -152,6 +153,7 @@ require ( github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect + github.com/DataDog/zstd v1.5.5 // indirect github.com/Intevation/gval v1.3.0 // indirect github.com/Intevation/jsonpath v0.2.1 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect @@ -187,7 +189,7 @@ require ( github.com/briandowns/spinner v1.23.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect - github.com/cloudflare/circl v1.3.7 // indirect + github.com/cloudflare/circl v1.3.8 // indirect github.com/containerd/cgroups/v3 v3.0.2 // indirect github.com/containerd/containerd/api v1.7.19 // indirect github.com/containerd/continuity v0.4.3 // indirect @@ -359,7 +361,7 @@ require ( github.com/tklauser/numcpus v0.7.0 // indirect github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 // indirect github.com/transparency-dev/merkle v0.0.2 // indirect - github.com/ulikunitz/xz v0.5.11 // indirect + github.com/ulikunitz/xz v0.5.12 // indirect github.com/vbatts/tar-split v0.11.5 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect @@ -367,6 +369,7 @@ require ( github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/yashtewari/glob-intersection v0.2.0 // indirect github.com/yuin/gopher-lua v1.1.1 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect diff --git a/go.sum b/go.sum index eafeea1e389b..51d43bf95aa1 100644 --- a/go.sum +++ b/go.sum @@ -245,6 +245,8 @@ github.com/CycloneDX/cyclonedx-go v0.9.1 h1:yffaWOZsv77oTJa/SdVZYdgAgFioCeycBUKk github.com/CycloneDX/cyclonedx-go v0.9.1/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= +github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= +github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible h1:juIaKLLVhqzP55d8x4cSVgwyQv76Z55/fRv/UBr2KkQ= github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs= github.com/Intevation/gval v1.3.0 h1:+Ze5sft5MmGbZrHj06NVUbcxCb67l9RaPTLMNr37mjw= @@ -461,8 +463,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= -github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI= +github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -1219,6 +1221,8 @@ github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= +github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg= +github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI= github.com/sassoftware/relic v7.2.1+incompatible h1:Pwyh1F3I0r4clFJXkSI8bOyJINGqpgjJU3DYAZeI05A= github.com/sassoftware/relic v7.2.1+incompatible/go.mod h1:CWfAxv73/iLZ17rbyhIEq3K9hs5w6FpNMdUT//qR+zk= github.com/sassoftware/relic/v7 v7.6.2 h1:rS44Lbv9G9eXsukknS4mSjIAuuX+lMq/FnStgmZlUv4= @@ -1344,8 +1348,8 @@ github.com/twitchtv/twirp v8.1.3+incompatible h1:+F4TdErPgSUbMZMwp13Q/KgDVuI7HJX github.com/twitchtv/twirp v8.1.3+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= -github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= +github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= @@ -1368,6 +1372,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yashtewari/glob-intersection v0.2.0 h1:8iuHdN88yYuCzCdjt0gDe+6bAhUwBeEWqThExu54RFg= diff --git a/magefiles/magefile.go b/magefiles/magefile.go index b1dbcd3439ad..06ebd7e665e1 100644 --- a/magefiles/magefile.go +++ b/magefiles/magefile.go @@ -16,6 +16,8 @@ import ( "github.com/magefile/mage/sh" "github.com/magefile/mage/target" + //mage:import rpm + rpm "github.com/aquasecurity/trivy/pkg/fanal/analyzer/pkg/rpm/testdata" // Trivy packages should not be imported in Mage (see https://github.com/aquasecurity/trivy/pull/4242), // but this package doesn't have so many dependencies, and Mage is still fast. "github.com/aquasecurity/trivy/pkg/log" @@ -268,7 +270,7 @@ func compileWasmModules(pattern string) error { // Unit runs unit tests func (t Test) Unit() error { - mg.Deps(t.GenerateModules) + mg.Deps(t.GenerateModules, rpm.Fixtures) return sh.RunWithV(ENV, "go", "test", "-v", "-short", "-coverprofile=coverage.txt", "-covermode=atomic", "./...") } diff --git a/mkdocs.yml b/mkdocs.yml index 60ed74306674..abe494df9dd9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -78,7 +78,6 @@ nav: - Azure Linux (CBL-Mariner): docs/coverage/os/azure.md - CentOS: docs/coverage/os/centos.md - Chainguard: docs/coverage/os/chainguard.md - - Conda: docs/coverage/os/conda.md - Debian: docs/coverage/os/debian.md - Oracle Linux: docs/coverage/os/oracle.md - Photon OS: docs/coverage/os/photon.md @@ -88,7 +87,6 @@ nav: - Ubuntu: docs/coverage/os/ubuntu.md - Wolfi: docs/coverage/os/wolfi.md - Google Distroless (Images): docs/coverage/os/google-distroless.md - - Bitnami (Images): docs/coverage/os/bitnami.md - Language: - Overview: docs/coverage/language/index.md - C/C++: docs/coverage/language/c.md @@ -112,6 +110,10 @@ nav: - Helm: docs/coverage/iac/helm.md - Kubernetes: docs/coverage/iac/kubernetes.md - Terraform: docs/coverage/iac/terraform.md + - Others: + - Bitnami Images: docs/coverage/others/bitnami.md + - Conda: docs/coverage/others/conda.md + - RPM Archives: docs/coverage/others/rpm.md - Kubernetes: docs/coverage/kubernetes.md - Configuration: - Overview: docs/configuration/index.md diff --git a/pkg/commands/artifact/run.go b/pkg/commands/artifact/run.go index 0c9560014a0a..49c7d3b34296 100644 --- a/pkg/commands/artifact/run.go +++ b/pkg/commands/artifact/run.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "os" "slices" "github.com/hashicorp/go-multierror" @@ -457,6 +458,12 @@ func disabledAnalyzers(opts flag.Options) []analyzer.Type { analyzers = append(analyzers, analyzer.TypeExecutable) } + // Disable RPM archive analyzer unless the environment variable is set + // TODO: add '--enable-analyzers' and delete this environment variable + if os.Getenv("TRIVY_EXPERIMENTAL_RPM_ARCHIVE") == "" { + analyzers = append(analyzers, analyzer.TypeRpmArchive) + } + return analyzers } diff --git a/pkg/fanal/analyzer/const.go b/pkg/fanal/analyzer/const.go index 197c0033296e..a9733d4b6076 100644 --- a/pkg/fanal/analyzer/const.go +++ b/pkg/fanal/analyzer/const.go @@ -32,6 +32,7 @@ const ( TypeDpkg Type = "dpkg" TypeDpkgLicense Type = "dpkg-license" // For analyzing licenses TypeRpm Type = "rpm" + TypeRpmArchive Type = "rpm-archive" TypeRpmqa Type = "rpmqa" // OS Package Repository diff --git a/pkg/fanal/analyzer/pkg/rpm/archive.go b/pkg/fanal/analyzer/pkg/rpm/archive.go new file mode 100644 index 000000000000..e9db78c6c648 --- /dev/null +++ b/pkg/fanal/analyzer/pkg/rpm/archive.go @@ -0,0 +1,161 @@ +package rpm + +import ( + "context" + "errors" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/package-url/packageurl-go" + "github.com/sassoftware/go-rpmutils" + "golang.org/x/xerrors" + + "github.com/aquasecurity/trivy/pkg/fanal/analyzer" + "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/scanner/utils" +) + +const archiveVersion = 1 + +func init() { + analyzer.RegisterAnalyzer(newRPMArchiveAnalyzer()) +} + +type rpmArchiveAnalyzer struct { + logger *log.Logger +} + +func newRPMArchiveAnalyzer() *rpmArchiveAnalyzer { + return &rpmArchiveAnalyzer{ + logger: log.WithPrefix("rpm-archive"), + } +} + +func (a *rpmArchiveAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) { + rpm, err := rpmutils.ReadRpm(input.Content) + if err != nil { + return nil, xerrors.Errorf("failed to read rpm (%s): %w", input.FilePath, err) + } + pkg, err := a.parseHeader(rpm.Header) + if err != nil { + return nil, xerrors.Errorf("failed to parse rpm header: %w", err) + } + pkg.FilePath = input.FilePath + pkg.Identifier.PURL = a.generatePURL(&pkg) + + return &analyzer.AnalysisResult{ + PackageInfos: []types.PackageInfo{ + { + FilePath: input.FilePath, + Packages: types.Packages{pkg}, + }, + }, + }, nil +} + +func (a *rpmArchiveAnalyzer) parseHeader(h *rpmutils.RpmHeader) (types.Package, error) { + if h == nil { + return types.Package{}, errors.New("rpm header is nil") + } + // Getting metadata + nevra, err := h.GetNEVRA() + if a.unexpectedError(err) != nil { + return types.Package{}, xerrors.Errorf("failed to get NEVRA: %w", err) + } + epoch, err := strconv.Atoi(nevra.Epoch) + if a.unexpectedError(err) != nil { + return types.Package{}, xerrors.Errorf("failed to convert epoch to int (%s): %w", nevra.Name, err) + } + licenses, err := h.GetStrings(rpmutils.LICENSE) + if a.unexpectedError(err) != nil { + return types.Package{}, xerrors.Errorf("failed to get licenses: %w", err) + } + srcName, srcVer, srcRel, err := a.parseSourceRPM(h) + if err != nil { + return types.Package{}, xerrors.Errorf("failed to parse source rpm: %w", err) + } + vendor, err := h.GetString(rpmutils.VENDOR) + if a.unexpectedError(err) != nil { + return types.Package{}, xerrors.Errorf("failed to get vendor: %w", err) + } + + // TODO: add the const to go-rpmutils + // cf. https://github.com/rpm-software-management/rpm/blob/rpm-4.16.0-release/lib/rpmtag.h#L375 + const modularityLabelTag = 5096 + modularityLabel, err := h.GetString(modularityLabelTag) + if a.unexpectedError(err) != nil { + return types.Package{}, xerrors.Errorf("failed to get modularitylabel: %w", err) + } + + return types.Package{ + Name: nevra.Name, + Version: nevra.Version, + Release: nevra.Release, + Epoch: epoch, + Arch: nevra.Arch, + SrcName: srcName, + SrcVersion: srcVer, + SrcRelease: srcRel, + SrcEpoch: epoch, + Licenses: licenses, + Maintainer: vendor, + Modularitylabel: modularityLabel, + }, nil +} + +func (a *rpmArchiveAnalyzer) parseSourceRPM(h *rpmutils.RpmHeader) (string, string, string, error) { + sourceRpm, err := h.GetString(rpmutils.SOURCERPM) + if a.unexpectedError(err) != nil { + return "", "", "", xerrors.Errorf("failed to get source rpm: %w", err) + } else if sourceRpm == "(none)" || sourceRpm == "" { + return "", "", "", nil + } + + srcName, srcVer, srcRel, err := splitFileName(sourceRpm) + if err != nil { + a.logger.Debug("Invalid Source RPM Found", log.String("sourcerpm", sourceRpm)) + } + return srcName, srcVer, srcRel, nil +} + +func (a *rpmArchiveAnalyzer) generatePURL(pkg *types.Package) *packageurl.PackageURL { + vendor := strings.ToLower(pkg.Maintainer) + + // TODO: Handle more vendors + var ns string + switch { + case strings.Contains(vendor, "red hat"): + ns = "redhat" + case strings.Contains(vendor, "fedora"): + ns = "fedora" + case strings.Contains(vendor, "opensuse"): + ns = "opensuse" + case strings.Contains(vendor, "suse"): + ns = "suse" + } + return packageurl.NewPackageURL(packageurl.TypeRPM, ns, pkg.Name, utils.FormatVersion(*pkg), nil, "") +} + +func (a *rpmArchiveAnalyzer) unexpectedError(err error) error { + var rerr rpmutils.NoSuchTagError + if errors.As(err, &rerr) { + a.logger.Debug("RPM tag not found", log.Err(rerr)) + return nil + } + return err +} + +func (a *rpmArchiveAnalyzer) Required(filePath string, _ os.FileInfo) bool { + return filepath.Ext(filePath) == ".rpm" +} + +func (a *rpmArchiveAnalyzer) Type() analyzer.Type { + return analyzer.TypeRpmArchive +} + +func (a *rpmArchiveAnalyzer) Version() int { + return archiveVersion +} diff --git a/pkg/fanal/analyzer/pkg/rpm/archive_test.go b/pkg/fanal/analyzer/pkg/rpm/archive_test.go new file mode 100644 index 000000000000..b9ac0a44ee53 --- /dev/null +++ b/pkg/fanal/analyzer/pkg/rpm/archive_test.go @@ -0,0 +1,81 @@ +package rpm + +import ( + "context" + "os" + "strings" + "testing" + + "github.com/package-url/packageurl-go" + "github.com/samber/lo" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/aquasecurity/trivy/pkg/fanal/analyzer" + "github.com/aquasecurity/trivy/pkg/fanal/types" +) + +func Test_rpmArchiveAnalyzer_Analyze(t *testing.T) { + tests := []struct { + name string + input analyzer.AnalysisInput + want *analyzer.AnalysisResult + wantErr require.ErrorAssertionFunc + }{ + { + name: "valid", + input: analyzer.AnalysisInput{ + FilePath: "testdata/valid.rpm", + Content: lo.Must(os.Open("testdata/socat-1.7.3.2-2.el7.x86_64.rpm")), // Must run 'mage rpm:fixtures' before this test + }, + want: &analyzer.AnalysisResult{ + PackageInfos: []types.PackageInfo{ + { + FilePath: "testdata/valid.rpm", + Packages: types.Packages{ + { + Name: "socat", + Version: "1.7.3.2", + Release: "2.el7", + Arch: "x86_64", + SrcName: "socat", + SrcVersion: "1.7.3.2", + SrcRelease: "2.el7", + FilePath: "testdata/valid.rpm", + Licenses: []string{ + "GPLv2", + }, + Maintainer: "Red Hat, Inc.", + Identifier: types.PkgIdentifier{ + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeRPM, + Namespace: "redhat", + Name: "socat", + Version: "1.7.3.2-2.el7", + }, + }, + }, + }, + }, + }, + }, + wantErr: require.NoError, + }, + { + name: "broken", + input: analyzer.AnalysisInput{ + FilePath: "testdata/broken.rpm", + Content: strings.NewReader(`broken`), + }, + wantErr: require.Error, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + a := newRPMArchiveAnalyzer() + got, err := a.Analyze(context.Background(), tt.input) + tt.wantErr(t, err) + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/pkg/fanal/analyzer/pkg/rpm/testdata/fixture.go b/pkg/fanal/analyzer/pkg/rpm/testdata/fixture.go new file mode 100644 index 000000000000..c9b1c0779f61 --- /dev/null +++ b/pkg/fanal/analyzer/pkg/rpm/testdata/fixture.go @@ -0,0 +1,63 @@ +package rpm + +import ( + "io" + "log/slog" + "net/http" + "os" + "path" + "path/filepath" + "runtime" + + "github.com/magefile/mage/target" + "golang.org/x/xerrors" +) + +const url = "https://mirror.openshift.com/pub/openshift-v4/amd64/dependencies/rpms/4.10-beta/socat-1.7.3.2-2.el7.x86_64.rpm" + +// Fixtures downloads RPM files for unit tests +func Fixtures() error { + _, filePath, _, _ := runtime.Caller(0) + dir := filepath.Dir(filePath) + dst := filepath.Join(dir, path.Base(url)) + + // Download the file only when it is needed + if updated, err := target.Path(dst, filePath); err != nil { + return err + } else if !updated { + return nil + } + return downloadFile(url, dst) +} + +// downloadFile downloads a file from the given URL and saves it with the original filename +// TODO: move this function to a common package for Mage +func downloadFile(url, dst string) error { + slog.Info("Downloading...", slog.String("url", url)) + + // Send a GET request to the URL + resp, err := http.Get(url) + if err != nil { + return xerrors.Errorf("error sending GET request: %v", err) + } + defer resp.Body.Close() + + // Check if the response status code is OK (200) + if resp.StatusCode != http.StatusOK { + return xerrors.Errorf("unexpected status code: %d", resp.StatusCode) + } + + // Create a new file with the extracted filename + out, err := os.Create(dst) + if err != nil { + return xerrors.Errorf("error creating file: %v", err) + } + defer out.Close() + + // Copy the response body to the file + if _, err = io.Copy(out, resp.Body); err != nil { + return xerrors.Errorf("error writing to file: %v", err) + } + + return nil +} diff --git a/pkg/fanal/applier/docker.go b/pkg/fanal/applier/docker.go index c1c21f236b22..6d1967497ab9 100644 --- a/pkg/fanal/applier/docker.go +++ b/pkg/fanal/applier/docker.go @@ -220,7 +220,7 @@ func ApplyLayers(layers []ftypes.BlobInfo) ftypes.ArtifactDetail { mergedLayer.Packages[i].InstalledFiles = installedFiles } - if mergedLayer.OS.Family != "" { + if mergedLayer.OS.Family != "" && pkg.Identifier.PURL == nil { mergedLayer.Packages[i].Identifier.PURL = newPURL(mergedLayer.OS.Family, types.Metadata{OS: &mergedLayer.OS}, pkg) } mergedLayer.Packages[i].Identifier.UID = dependency.UID("", pkg) From fcaea740808d5784c120e5c5d65f5f94e1d931d4 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Thu, 3 Oct 2024 10:27:25 +0600 Subject: [PATCH 32/94] fix(misconf): not to warn about missing selectors of libraries (#7638) Signed-off-by: nikpivkin --- pkg/iac/rego/load.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pkg/iac/rego/load.go b/pkg/iac/rego/load.go index 8f1033ecfa2d..7356384a3327 100644 --- a/pkg/iac/rego/load.go +++ b/pkg/iac/rego/load.go @@ -302,14 +302,17 @@ func (s *Scanner) filterModules(retriever *MetadataRetriever) error { } if len(meta.InputOptions.Selectors) == 0 { - s.logger.Warn( - "Module has no input selectors - it will be loaded for all inputs!", - log.FilePath(module.Package.Location.File), - log.String("module", name), - ) + if !meta.Library { + s.logger.Warn( + "Module has no input selectors - it will be loaded for all inputs!", + log.FilePath(module.Package.Location.File), + log.String("module", name), + ) + } filtered[name] = module continue } + for _, selector := range meta.InputOptions.Selectors { if selector.Type == string(s.sourceType) { filtered[name] = module From d24640158fb215cc48bcc2e9fcd2676c61d0c480 Mon Sep 17 00:00:00 2001 From: Aqua Security automated builds <54269356+aqua-bot@users.noreply.github.com> Date: Thu, 3 Oct 2024 07:55:35 +0300 Subject: [PATCH 33/94] release: v0.56.0 [main] (#7447) --- .release-please-manifest.json | 2 +- CHANGELOG.md | 45 +++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index aeec62f4b8cc..208746a81be3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{".":"0.55.0"} +{".":"0.56.0"} diff --git a/CHANGELOG.md b/CHANGELOG.md index 19df5eb64851..afc44ba7a956 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,50 @@ # Changelog +## [0.56.0](https://github.com/aquasecurity/trivy/compare/v0.55.0...v0.56.0) (2024-10-03) + + +### Features + +* **java:** add empty versions if `pom.xml` dependency versions can't be detected ([#7520](https://github.com/aquasecurity/trivy/issues/7520)) ([b836232](https://github.com/aquasecurity/trivy/commit/b8362321adb2af220830c5de31c29978423d47da)) +* **license:** improve license normalization ([#7131](https://github.com/aquasecurity/trivy/issues/7131)) ([6472e3c](https://github.com/aquasecurity/trivy/commit/6472e3c9da2a8e7ba41598a45c80df8f18e57d4c)) +* **misconf:** add ability to disable checks by ID ([#7536](https://github.com/aquasecurity/trivy/issues/7536)) ([ef0a27d](https://github.com/aquasecurity/trivy/commit/ef0a27d515ff80762bf1959d44a8bde017ae06ec)) +* **misconf:** Register checks only when needed ([#7435](https://github.com/aquasecurity/trivy/issues/7435)) ([f768d3a](https://github.com/aquasecurity/trivy/commit/f768d3a767a99a86b0372f19d9f49a2de35dbe59)) +* **misconf:** Support `--skip-*` for all included modules ([#7579](https://github.com/aquasecurity/trivy/issues/7579)) ([c0e8da3](https://github.com/aquasecurity/trivy/commit/c0e8da3828e9d3a0b30d1f6568037db8dc827765)) +* **secret:** enhance secret scanning for python binary files ([#7223](https://github.com/aquasecurity/trivy/issues/7223)) ([60725f8](https://github.com/aquasecurity/trivy/commit/60725f879ba014c5c57583db6afc290b78facae8)) +* support multiple DB repositories for vulnerability and Java DB ([#7605](https://github.com/aquasecurity/trivy/issues/7605)) ([3562529](https://github.com/aquasecurity/trivy/commit/3562529ddfb26d301311ed450c192e17011353df)) +* support RPM archives ([#7628](https://github.com/aquasecurity/trivy/issues/7628)) ([69bf7e0](https://github.com/aquasecurity/trivy/commit/69bf7e00ea5ab483692db830fdded26a31f03183)) +* **suse:** added SUSE Linux Enterprise Micro support ([#7294](https://github.com/aquasecurity/trivy/issues/7294)) ([efdb68d](https://github.com/aquasecurity/trivy/commit/efdb68d3b9ddf9dfaf45ea5855b31c43a4366bab)) + + +### Bug Fixes + +* allow access to '..' in mapfs ([#7575](https://github.com/aquasecurity/trivy/issues/7575)) ([a8fbe46](https://github.com/aquasecurity/trivy/commit/a8fbe46119adbd89f827a75c75b9e97d392f1842)) +* **db:** check `DownloadedAt` for `trivy-java-db` ([#7592](https://github.com/aquasecurity/trivy/issues/7592)) ([13ef3e7](https://github.com/aquasecurity/trivy/commit/13ef3e7d62ba2bcb3a04d7b44f79b1299674b480)) +* **java:** use `dependencyManagement` from root/child pom's for dependencies from parents ([#7497](https://github.com/aquasecurity/trivy/issues/7497)) ([5442949](https://github.com/aquasecurity/trivy/commit/54429497e7d6a87eac236771d4efb8a5a7faaac5)) +* **license:** stop spliting a long license text ([#7336](https://github.com/aquasecurity/trivy/issues/7336)) ([4926da7](https://github.com/aquasecurity/trivy/commit/4926da79de901fba73819d71845ec0355b68ae0f)) +* **misconf:** Disable deprecated checks by default ([#7632](https://github.com/aquasecurity/trivy/issues/7632)) ([82e2adc](https://github.com/aquasecurity/trivy/commit/82e2adc6f8e68d0cc0021031170c2adb60d213ba)) +* **misconf:** disable DS016 check for image history analyzer ([#7540](https://github.com/aquasecurity/trivy/issues/7540)) ([de40df9](https://github.com/aquasecurity/trivy/commit/de40df9408d6d856a3ad384ec9f086edce3aa382)) +* **misconf:** escape all special sequences ([#7558](https://github.com/aquasecurity/trivy/issues/7558)) ([ea0cf03](https://github.com/aquasecurity/trivy/commit/ea0cf0379aff0348fde87356dab37947800fc1b6)) +* **misconf:** Fix logging typo ([#7473](https://github.com/aquasecurity/trivy/issues/7473)) ([56db43c](https://github.com/aquasecurity/trivy/commit/56db43c24f4f6be92891be85faaf9492cad516ac)) +* **misconf:** Fixed scope for China Cloud ([#7560](https://github.com/aquasecurity/trivy/issues/7560)) ([37d549e](https://github.com/aquasecurity/trivy/commit/37d549e5b86a1c5dce6710fbfd2310aec9abe949)) +* **misconf:** not to warn about missing selectors of libraries ([#7638](https://github.com/aquasecurity/trivy/issues/7638)) ([fcaea74](https://github.com/aquasecurity/trivy/commit/fcaea740808d5784c120e5c5d65f5f94e1d931d4)) +* **oracle:** Update EOL date for Oracle 7 ([#7480](https://github.com/aquasecurity/trivy/issues/7480)) ([dd0a64a](https://github.com/aquasecurity/trivy/commit/dd0a64a1cf0cd76e6f81e3ff55fa6ccb95ce3c3d)) +* **report:** change a receiver of MarshalJSON ([#7483](https://github.com/aquasecurity/trivy/issues/7483)) ([927c6e0](https://github.com/aquasecurity/trivy/commit/927c6e0c9d4d4a3f1be00f0f661c1d18325d9440)) +* **report:** fix error with unmarshal of `ExperimentalModifiedFindings` ([#7463](https://github.com/aquasecurity/trivy/issues/7463)) ([7ff9aff](https://github.com/aquasecurity/trivy/commit/7ff9aff2739b2eee4a98175b98914795e4077060)) +* **sbom:** export bom-ref when converting a package to a component ([#7340](https://github.com/aquasecurity/trivy/issues/7340)) ([5dd94eb](https://github.com/aquasecurity/trivy/commit/5dd94ebc1ffe3f1df511dee6381f92a5daefadf2)) +* **sbom:** parse type `framework` as `library` when unmarshalling `CycloneDX` files ([#7527](https://github.com/aquasecurity/trivy/issues/7527)) ([aeb7039](https://github.com/aquasecurity/trivy/commit/aeb7039d7ce090e243d29f0bf16c9e4e24252a01)) +* **secret:** change grafana token regex to find them without unquoted ([#7627](https://github.com/aquasecurity/trivy/issues/7627)) ([3e1fa21](https://github.com/aquasecurity/trivy/commit/3e1fa2100074e840bacdd65947425b08750b7d9a)) + + +### Performance Improvements + +* **misconf:** use port ranges instead of enumeration ([#7549](https://github.com/aquasecurity/trivy/issues/7549)) ([1f9fc13](https://github.com/aquasecurity/trivy/commit/1f9fc13da4a1e7c76c978e4f8e119bfd61a0480e)) + + +### Reverts + +* **java:** stop supporting of `test` scope for `pom.xml` files ([#7488](https://github.com/aquasecurity/trivy/issues/7488)) ([b0222fe](https://github.com/aquasecurity/trivy/commit/b0222feeb586ec59904bb321fda8f3f22496d07b)) + ## [0.55.0](https://github.com/aquasecurity/trivy/compare/v0.54.0...v0.55.0) (2024-09-03) From cb0b3a9279b31810ecd686a385e5140e567ce86f Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 3 Oct 2024 06:56:59 +0200 Subject: [PATCH 34/94] feat(cli): error out when ignore file cannot be found (#7624) --- pkg/flag/report_flags.go | 6 ++++++ pkg/flag/report_flags_test.go | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/pkg/flag/report_flags.go b/pkg/flag/report_flags.go index 67d553b65553..d69443e89547 100644 --- a/pkg/flag/report_flags.go +++ b/pkg/flag/report_flags.go @@ -6,6 +6,7 @@ import ( "github.com/mattn/go-shellwords" "github.com/samber/lo" + "github.com/spf13/viper" "golang.org/x/xerrors" dbTypes "github.com/aquasecurity/trivy-db/pkg/types" @@ -14,6 +15,7 @@ import ( "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/result" "github.com/aquasecurity/trivy/pkg/types" + "github.com/aquasecurity/trivy/pkg/utils/fsutils" xstrings "github.com/aquasecurity/trivy/pkg/x/strings" ) @@ -238,6 +240,10 @@ func (f *ReportFlagGroup) ToOptions() (ReportOptions, error) { } } + if viper.IsSet(f.IgnoreFile.ConfigName) && !fsutils.FileExists(f.IgnoreFile.Value()) { + return ReportOptions{}, xerrors.Errorf("ignore file not found: %s", f.IgnoreFile.Value()) + } + return ReportOptions{ Format: format, ReportFormat: f.ReportFormat.Value(), diff --git a/pkg/flag/report_flags_test.go b/pkg/flag/report_flags_test.go index 9440bf373905..b113d7c62f97 100644 --- a/pkg/flag/report_flags_test.go +++ b/pkg/flag/report_flags_test.go @@ -209,4 +209,16 @@ func TestReportFlagGroup_ToOptions(t *testing.T) { assert.Equal(t, tt.wantLogs, out.Messages(), tt.name) }) } + + t.Run("Error on non existing ignore file", func(t *testing.T) { + t.Cleanup(viper.Reset) + + setValue(flag.IgnoreFileFlag.ConfigName, string("doesntexist")) + f := &flag.ReportFlagGroup{ + IgnoreFile: flag.IgnoreFileFlag.Clone(), + } + + _, err := f.ToOptions() + assert.ErrorContains(t, err, "ignore file not found: doesntexist") + }) } From 2c87f0cb794acd77446a273582ba1a45b9f18980 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Thu, 3 Oct 2024 18:11:58 +0600 Subject: [PATCH 35/94] fix(db): fix javadb downloading error handling (#7642) Signed-off-by: nikpivkin --- pkg/javadb/client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/javadb/client.go b/pkg/javadb/client.go index 6d5b589bb5d1..835730109b02 100644 --- a/pkg/javadb/client.go +++ b/pkg/javadb/client.go @@ -104,10 +104,10 @@ func (u *Updater) downloadDB(ctx context.Context) error { Quiet: u.quiet, } if err := artifacts.Download(ctx, u.dbDir, downloadOpt); err != nil { - return xerrors.Errorf("failed to download vulnerability DB: %w", err) + return xerrors.Errorf("failed to download Java DB: %w", err) } - return xerrors.New("failed to download Java DB from any source") + return nil } func Init(cacheDir string, javaDBRepositories []name.Reference, skip, quiet bool, registryOption ftypes.RegistryOptions) { From ab3a3b2e6ed15db90967084fac825ddb2f50e70d Mon Sep 17 00:00:00 2001 From: Pierre Baumard Date: Mon, 7 Oct 2024 09:41:01 +0200 Subject: [PATCH 36/94] docs(report): Improve SARIF reporting doc (#7655) --- docs/docs/configuration/reporting.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/docs/configuration/reporting.md b/docs/docs/configuration/reporting.md index 17bf0b864283..fcbde0b106ff 100644 --- a/docs/docs/configuration/reporting.md +++ b/docs/docs/configuration/reporting.md @@ -5,7 +5,7 @@ Trivy supports the following formats: - Table - JSON -- [SARIF](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning) +- [SARIF][sarif-home] - Template - SBOM - GitHub dependency snapshot @@ -252,13 +252,15 @@ $ trivy image -f json -o results.json golang:1.12-alpine | Secret | ✓ | | License | ✓ | -[SARIF][sarif] can be generated with the `--format sarif` flag. +[SARIF][sarif-home] (Static Analysis Results Interchange Format) complying with [SARIF 2.1.0 OASIS standard][sarif-spec] can be generated with the `--format sarif` flag. ``` $ trivy image --format sarif -o report.sarif golang:1.12-alpine ``` -This SARIF file can be uploaded to GitHub code scanning results, and there is a [Trivy GitHub Action][action] for automating this process. +This SARIF file can be uploaded to several platforms, including: +- [GitHub code scanning results][sarif-github], and there is a [Trivy GitHub Action][action] for automating this process; +- [SonarQube][sarif-sonar]. ### GitHub dependency snapshot Trivy supports the following packages. @@ -430,7 +432,10 @@ $ trivy convert --format table --severity CRITICAL result.json [cargo-auditable]: https://github.com/rust-secure-code/cargo-auditable/ [action]: https://github.com/aquasecurity/trivy-action [asff]: ../../tutorials/integrations/aws-security-hub.md -[sarif]: https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/managing-results-from-code-scanning +[sarif-home]: https://sarifweb.azurewebsites.net +[sarif-spec]: https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html +[sarif-github]: https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning +[sarif-sonar]: https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/importing-external-issues/importing-issues-from-sarif-reports/ [sprig]: http://masterminds.github.io/sprig/ [github-sbom]: https://docs.github.com/en/rest/dependency-graph/dependency-submission?apiVersion=2022-11-28#about-dependency-submissions [github-sbom-submit]: https://docs.github.com/en/rest/dependency-graph/dependency-submission?apiVersion=2022-11-28#create-a-snapshot-of-dependencies-for-a-repository @@ -450,4 +455,4 @@ $ trivy convert --format table --severity CRITICAL result.json [gradle-lockfile]: ../coverage/language/java.md#gradlelock [sbt-lockfile]: ../coverage/language/java.md#sbt [pubspec-lock]: ../coverage/language/dart.md#dart -[cargo-binaries]: ../coverage/language/rust.md#binaries \ No newline at end of file +[cargo-binaries]: ../coverage/language/rust.md#binaries From 015bb885ac414b91201fa9791eead395d878149c Mon Sep 17 00:00:00 2001 From: Pierre Baumard Date: Mon, 7 Oct 2024 13:31:59 +0200 Subject: [PATCH 37/94] fix(report): Fix invalid URI in SARIF report (#7645) Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> --- pkg/report/sarif.go | 37 ++++++++++++++++++++++++------------- pkg/report/sarif_test.go | 34 +++++++++++++++++----------------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/pkg/report/sarif.go b/pkg/report/sarif.go index a94dcccb2c9b..3bc3344611e2 100644 --- a/pkg/report/sarif.go +++ b/pkg/report/sarif.go @@ -5,6 +5,7 @@ import ( "fmt" "html" "io" + "net/url" "path/filepath" "regexp" "strings" @@ -15,6 +16,7 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/artifact" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/types" ) @@ -61,9 +63,9 @@ type sarifData struct { helpMarkdown string resourceClass types.ResultClass severity string - url string + url *url.URL resultIndex int - artifactLocation string + artifactLocation *url.URL locationMessage string message string cvssScore string @@ -97,8 +99,8 @@ func (sw *SarifWriter) addSarifRule(data *sarifData) { "precision": "very-high", "security-severity": data.cvssScore, }) - if data.url != "" { - r.WithHelpURI(data.url) + if data.url != nil && data.url.String() != "" { + r.WithHelpURI(data.url.String()) } } @@ -109,7 +111,7 @@ func (sw *SarifWriter) addSarifResult(data *sarifData) { WithRuleIndex(data.resultIndex). WithMessage(sarif.NewTextMessage(data.message)). WithLevel(toSarifErrorLevel(data.severity)). - WithLocations(toSarifLocations(data.locations, data.artifactLocation, data.locationMessage)) + WithLocations(toSarifLocations(data.locations, data.artifactLocation.String(), data.locationMessage)) sw.run.AddResult(result) } @@ -163,9 +165,9 @@ func (sw *SarifWriter) Write(ctx context.Context, report types.Report) error { vulnerabilityId: vuln.VulnerabilityID, severity: vuln.Severity, cvssScore: getCVSSScore(vuln), - url: vuln.PrimaryURL, + url: toUri(vuln.PrimaryURL), resourceClass: res.Class, - artifactLocation: path, + artifactLocation: toUri(path), locationMessage: fmt.Sprintf("%v: %v@%v", path, vuln.PkgName, vuln.InstalledVersion), locations: sw.getLocations(vuln.PkgName, vuln.InstalledVersion, path, res.Packages), resultIndex: getRuleIndex(vuln.VulnerabilityID, ruleIndexes), @@ -186,9 +188,9 @@ func (sw *SarifWriter) Write(ctx context.Context, report types.Report) error { vulnerabilityId: misconf.ID, severity: misconf.Severity, cvssScore: severityToScore(misconf.Severity), - url: misconf.PrimaryURL, + url: toUri(misconf.PrimaryURL), resourceClass: res.Class, - artifactLocation: locationURI, + artifactLocation: toUri(locationURI), locationMessage: locationURI, locations: []location{ { @@ -213,9 +215,9 @@ func (sw *SarifWriter) Write(ctx context.Context, report types.Report) error { vulnerabilityId: secret.RuleID, severity: secret.Severity, cvssScore: severityToScore(secret.Severity), - url: builtinRulesUrl, + url: toUri(builtinRulesUrl), resourceClass: res.Class, - artifactLocation: target, + artifactLocation: toUri(target), locationMessage: target, locations: []location{ { @@ -242,9 +244,9 @@ func (sw *SarifWriter) Write(ctx context.Context, report types.Report) error { vulnerabilityId: id, severity: license.Severity, cvssScore: severityToScore(license.Severity), - url: license.Link, + url: toUri(license.Link), resourceClass: res.Class, - artifactLocation: target, + artifactLocation: toUri(target), resultIndex: getRuleIndex(id, ruleIndexes), shortDescription: desc, fullDescription: desc, @@ -348,6 +350,15 @@ func clearURI(s string) string { return strings.ReplaceAll(strings.ReplaceAll(s, "\\", "/"), "git::https:/", "") } +func toUri(str string) *url.URL { + uri, err := url.Parse(str) + if err != nil { + logger := log.WithPrefix("sarif") + logger.Error("Unable to parse URI", log.String("URI", str), log.Err(err)) + } + return uri +} + func (sw *SarifWriter) getLocations(name, version, path string, pkgs []ftypes.Package) []location { id := fmt.Sprintf("%s@%s@%s", path, name, version) locs, ok := sw.locationCache[id] diff --git a/pkg/report/sarif_test.go b/pkg/report/sarif_test.go index cf4bfea8eb0b..ce68fab06a8a 100644 --- a/pkg/report/sarif_test.go +++ b/pkg/report/sarif_test.go @@ -41,7 +41,7 @@ func TestReportWriter_Sarif(t *testing.T) { }, Results: types.Results{ { - Target: "library/test", + Target: "library/test 1", Class: types.ClassOSPkg, Packages: []ftypes.Package{ { @@ -137,10 +137,10 @@ func TestReportWriter_Sarif(t *testing.T) { Message: sarif.Message{Text: lo.ToPtr("Package: foo\nInstalled Version: 1.2.3\nVulnerability CVE-2020-0001\nSeverity: HIGH\nFixed Version: 3.4.5\nLink: [CVE-2020-0001](https://avd.aquasec.com/nvd/cve-2020-0001)")}, Locations: []*sarif.Location{ { - Message: &sarif.Message{Text: lo.ToPtr("library/test: foo@1.2.3")}, + Message: &sarif.Message{Text: lo.ToPtr("library/test 1: foo@1.2.3")}, PhysicalLocation: &sarif.PhysicalLocation{ ArtifactLocation: &sarif.ArtifactLocation{ - URI: lo.ToPtr("library/test"), + URI: lo.ToPtr("library/test%201"), URIBaseId: lo.ToPtr("ROOTPATH"), }, Region: &sarif.Region{ @@ -152,10 +152,10 @@ func TestReportWriter_Sarif(t *testing.T) { }, }, { - Message: &sarif.Message{Text: lo.ToPtr("library/test: foo@1.2.3")}, + Message: &sarif.Message{Text: lo.ToPtr("library/test 1: foo@1.2.3")}, PhysicalLocation: &sarif.PhysicalLocation{ ArtifactLocation: &sarif.ArtifactLocation{ - URI: lo.ToPtr("library/test"), + URI: lo.ToPtr("library/test%201"), URIBaseId: lo.ToPtr("ROOTPATH"), }, Region: &sarif.Region{ @@ -192,7 +192,7 @@ func TestReportWriter_Sarif(t *testing.T) { input: types.Report{ Results: types.Results{ { - Target: "library/test", + Target: "library/test 1", Class: types.ClassConfig, Misconfigurations: []types.DetectedMisconfiguration{ { @@ -283,13 +283,13 @@ func TestReportWriter_Sarif(t *testing.T) { RuleID: lo.ToPtr("KSV001"), RuleIndex: lo.ToPtr[uint](0), Level: lo.ToPtr("error"), - Message: sarif.Message{Text: lo.ToPtr("Artifact: library/test\nType: \nVulnerability KSV001\nSeverity: HIGH\nMessage: Message\nLink: [KSV001](https://avd.aquasec.com/appshield/ksv001)")}, + Message: sarif.Message{Text: lo.ToPtr("Artifact: library/test 1\nType: \nVulnerability KSV001\nSeverity: HIGH\nMessage: Message\nLink: [KSV001](https://avd.aquasec.com/appshield/ksv001)")}, Locations: []*sarif.Location{ { - Message: &sarif.Message{Text: lo.ToPtr("library/test")}, + Message: &sarif.Message{Text: lo.ToPtr("library/test 1")}, PhysicalLocation: &sarif.PhysicalLocation{ ArtifactLocation: &sarif.ArtifactLocation{ - URI: lo.ToPtr("library/test"), + URI: lo.ToPtr("library/test%201"), URIBaseId: lo.ToPtr("ROOTPATH"), }, Region: &sarif.Region{ @@ -306,13 +306,13 @@ func TestReportWriter_Sarif(t *testing.T) { RuleID: lo.ToPtr("KSV002"), RuleIndex: lo.ToPtr[uint](1), Level: lo.ToPtr("error"), - Message: sarif.Message{Text: lo.ToPtr("Artifact: library/test\nType: \nVulnerability KSV002\nSeverity: CRITICAL\nMessage: Message\nLink: [KSV002](https://avd.aquasec.com/appshield/ksv002)")}, + Message: sarif.Message{Text: lo.ToPtr("Artifact: library/test 1\nType: \nVulnerability KSV002\nSeverity: CRITICAL\nMessage: Message\nLink: [KSV002](https://avd.aquasec.com/appshield/ksv002)")}, Locations: []*sarif.Location{ { - Message: &sarif.Message{Text: lo.ToPtr("library/test")}, + Message: &sarif.Message{Text: lo.ToPtr("library/test 1")}, PhysicalLocation: &sarif.PhysicalLocation{ ArtifactLocation: &sarif.ArtifactLocation{ - URI: lo.ToPtr("library/test"), + URI: lo.ToPtr("library/test%201"), URIBaseId: lo.ToPtr("ROOTPATH"), }, Region: &sarif.Region{ @@ -341,7 +341,7 @@ func TestReportWriter_Sarif(t *testing.T) { input: types.Report{ Results: types.Results{ { - Target: "library/test", + Target: "library/test 1", Class: types.ClassSecret, Secrets: []types.DetectedSecret{ { @@ -400,13 +400,13 @@ func TestReportWriter_Sarif(t *testing.T) { RuleID: lo.ToPtr("aws-secret-access-key"), RuleIndex: lo.ToPtr[uint](0), Level: lo.ToPtr("error"), - Message: sarif.Message{Text: lo.ToPtr("Artifact: library/test\nType: \nSecret AWS Secret Access Key\nSeverity: CRITICAL\nMatch: 'AWS_secret_KEY'=\"****************************************\"")}, + Message: sarif.Message{Text: lo.ToPtr("Artifact: library/test 1\nType: \nSecret AWS Secret Access Key\nSeverity: CRITICAL\nMatch: 'AWS_secret_KEY'=\"****************************************\"")}, Locations: []*sarif.Location{ { - Message: &sarif.Message{Text: lo.ToPtr("library/test")}, + Message: &sarif.Message{Text: lo.ToPtr("library/test 1")}, PhysicalLocation: &sarif.PhysicalLocation{ ArtifactLocation: &sarif.ArtifactLocation{ - URI: lo.ToPtr("library/test"), + URI: lo.ToPtr("library/test%201"), URIBaseId: lo.ToPtr("ROOTPATH"), }, Region: &sarif.Region{ @@ -495,7 +495,7 @@ func TestReportWriter_Sarif(t *testing.T) { Message: sarif.NewTextMessage(""), PhysicalLocation: &sarif.PhysicalLocation{ ArtifactLocation: &sarif.ArtifactLocation{ - URI: lo.ToPtr("OS Packages"), + URI: lo.ToPtr("OS%20Packages"), URIBaseId: lo.ToPtr("ROOTPATH"), }, Region: &sarif.Region{ From a585e95f3398631d9ad10505c5ff642fde21aef7 Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Mon, 7 Oct 2024 16:03:40 +0400 Subject: [PATCH 38/94] fix(redhat): include arch in PURL qualifiers (#7654) Signed-off-by: knqyf263 --- pkg/fanal/analyzer/pkg/rpm/archive.go | 9 ++++++++- pkg/fanal/analyzer/pkg/rpm/archive_test.go | 6 ++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pkg/fanal/analyzer/pkg/rpm/archive.go b/pkg/fanal/analyzer/pkg/rpm/archive.go index e9db78c6c648..2eda91e4a563 100644 --- a/pkg/fanal/analyzer/pkg/rpm/archive.go +++ b/pkg/fanal/analyzer/pkg/rpm/archive.go @@ -136,7 +136,14 @@ func (a *rpmArchiveAnalyzer) generatePURL(pkg *types.Package) *packageurl.Packag case strings.Contains(vendor, "suse"): ns = "suse" } - return packageurl.NewPackageURL(packageurl.TypeRPM, ns, pkg.Name, utils.FormatVersion(*pkg), nil, "") + var qualifiers packageurl.Qualifiers + if pkg.Arch != "" { + qualifiers = append(qualifiers, packageurl.Qualifier{ + Key: "arch", + Value: pkg.Arch, + }) + } + return packageurl.NewPackageURL(packageurl.TypeRPM, ns, pkg.Name, utils.FormatVersion(*pkg), qualifiers, "") } func (a *rpmArchiveAnalyzer) unexpectedError(err error) error { diff --git a/pkg/fanal/analyzer/pkg/rpm/archive_test.go b/pkg/fanal/analyzer/pkg/rpm/archive_test.go index b9ac0a44ee53..5e8475e171f6 100644 --- a/pkg/fanal/analyzer/pkg/rpm/archive_test.go +++ b/pkg/fanal/analyzer/pkg/rpm/archive_test.go @@ -52,6 +52,12 @@ func Test_rpmArchiveAnalyzer_Analyze(t *testing.T) { Namespace: "redhat", Name: "socat", Version: "1.7.3.2-2.el7", + Qualifiers: packageurl.Qualifiers{ + { + Key: "arch", + Value: "x86_64", + }, + }, }, }, }, From fdf203cd209aeb40f454bd12d121a54d6ed7a542 Mon Sep 17 00:00:00 2001 From: Dan Kirkwood Date: Mon, 7 Oct 2024 22:04:06 -0700 Subject: [PATCH 39/94] fix(repo): `git clone` output to Stderr (#7561) --- pkg/fanal/artifact/repo/git.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/fanal/artifact/repo/git.go b/pkg/fanal/artifact/repo/git.go index 8eb3d9af7f9d..4532b631c6b7 100644 --- a/pkg/fanal/artifact/repo/git.go +++ b/pkg/fanal/artifact/repo/git.go @@ -128,7 +128,7 @@ func cloneRepo(u *url.URL, artifactOpt artifact.Option) (string, error) { cloneOptions := git.CloneOptions{ URL: u.String(), Auth: gitAuth(), - Progress: os.Stdout, + Progress: os.Stderr, InsecureSkipTLS: artifactOpt.Insecure, } From 55b5a7e01b679f58b54b1e84a96da21d940eaf22 Mon Sep 17 00:00:00 2001 From: Pierre Baumard Date: Tue, 8 Oct 2024 19:01:49 +0200 Subject: [PATCH 40/94] docs(report): fix reporting doc format (#7671) --- docs/docs/configuration/reporting.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/docs/configuration/reporting.md b/docs/docs/configuration/reporting.md index fcbde0b106ff..39ecb6e5333c 100644 --- a/docs/docs/configuration/reporting.md +++ b/docs/docs/configuration/reporting.md @@ -259,11 +259,12 @@ $ trivy image --format sarif -o report.sarif golang:1.12-alpine ``` This SARIF file can be uploaded to several platforms, including: -- [GitHub code scanning results][sarif-github], and there is a [Trivy GitHub Action][action] for automating this process; -- [SonarQube][sarif-sonar]. + +- [GitHub code scanning results][sarif-github], and there is a [Trivy GitHub Action][action] for automating this process +- [SonarQube][sarif-sonar] ### GitHub dependency snapshot -Trivy supports the following packages. +Trivy supports the following packages: - [OS packages][os_packages] - [Language-specific packages][language_packages] From 1f2e91b02b3606dd11963002a8cfac7962f3478f Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Wed, 9 Oct 2024 09:53:27 +0400 Subject: [PATCH 41/94] fix(sbom): add options for DBs in private registries (#7660) Signed-off-by: knqyf263 --- docs/docs/references/configuration/cli/trivy_sbom.md | 3 +++ pkg/commands/app.go | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/docs/references/configuration/cli/trivy_sbom.md b/docs/docs/references/configuration/cli/trivy_sbom.md index f09453845518..4eaedcf17aa5 100644 --- a/docs/docs/references/configuration/cli/trivy_sbom.md +++ b/docs/docs/references/configuration/cli/trivy_sbom.md @@ -47,12 +47,14 @@ 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 + --password strings password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons. --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 --redis-tls enable redis TLS with public certificates, if using redis as cache backend + --registry-token string registry token --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") --sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor) --scanners strings comma-separated list of what security issues to detect (vuln,license) (default [vuln]) @@ -67,6 +69,7 @@ trivy sbom [flags] SBOM_PATH -t, --template string output template --token string for authentication in client/server mode --token-header string specify a header name for token in client/server mode (default "Trivy-Token") + --username strings username. Comma-separated usernames allowed. --vex strings [EXPERIMENTAL] VEX sources ("repo", "oci" or file path) ``` diff --git a/pkg/commands/app.go b/pkg/commands/app.go index 23b44fdec553..bdba2fa12ac7 100644 --- a/pkg/commands/app.go +++ b/pkg/commands/app.go @@ -1143,7 +1143,8 @@ func NewSBOMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { CacheFlagGroup: flag.NewCacheFlagGroup(), DBFlagGroup: flag.NewDBFlagGroup(), PackageFlagGroup: flag.NewPackageFlagGroup(), - RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode + RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode + RegistryFlagGroup: flag.NewRegistryFlagGroup(), // for DBs in private registries ReportFlagGroup: reportFlagGroup, ScanFlagGroup: scanFlagGroup, VulnerabilityFlagGroup: flag.NewVulnerabilityFlagGroup(), From 27117f81d52483c3ceec56fe56ac298e242fbc9a Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Wed, 9 Oct 2024 14:31:15 +0400 Subject: [PATCH 42/94] feat(cli): add `trivy auth` (#7664) Signed-off-by: knqyf263 Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> --- contrib/Trivy.gitlab-ci.yml | 2 +- .../docs/advanced/private-registries/index.md | 34 +++-- .../references/configuration/cli/trivy.md | 1 + .../configuration/cli/trivy_auth.md | 29 ++++ .../configuration/cli/trivy_auth_login.md | 41 +++++ .../configuration/cli/trivy_auth_logout.md | 38 +++++ .../configuration/cli/trivy_config.md | 1 + .../configuration/cli/trivy_filesystem.md | 1 + .../configuration/cli/trivy_image.md | 1 + .../configuration/cli/trivy_kubernetes.md | 1 + .../configuration/cli/trivy_repository.md | 1 + .../configuration/cli/trivy_rootfs.md | 1 + .../configuration/cli/trivy_sbom.md | 1 + .../configuration/cli/trivy_server.md | 1 + .../references/configuration/config-file.md | 3 + docs/docs/target/container_image.md | 2 +- go.mod | 2 +- integration/registry_test.go | 39 ++++- mkdocs.yml | 4 + pkg/commands/app.go | 58 +++++++ pkg/commands/auth/run.go | 109 ++++++++++++++ pkg/commands/auth/run_test.go | 142 ++++++++++++++++++ pkg/flag/registry_flags.go | 23 ++- 23 files changed, 512 insertions(+), 23 deletions(-) create mode 100644 docs/docs/references/configuration/cli/trivy_auth.md create mode 100644 docs/docs/references/configuration/cli/trivy_auth_login.md create mode 100644 docs/docs/references/configuration/cli/trivy_auth_logout.md create mode 100644 pkg/commands/auth/run.go create mode 100644 pkg/commands/auth/run_test.go diff --git a/contrib/Trivy.gitlab-ci.yml b/contrib/Trivy.gitlab-ci.yml index 66225b0dac06..a62e26301a20 100644 --- a/contrib/Trivy.gitlab-ci.yml +++ b/contrib/Trivy.gitlab-ci.yml @@ -12,9 +12,9 @@ Trivy_container_scanning: before_script: - export TRIVY_VERSION=${TRIVY_VERSION:-v0.19.2} - apk add --no-cache curl docker-cli - - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin ${TRIVY_VERSION} - curl -sSL -o /tmp/trivy-gitlab.tpl https://github.com/aquasecurity/trivy/raw/${TRIVY_VERSION}/contrib/gitlab.tpl + - trivy auth login --username "$CI_REGISTRY_USER" --password "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - trivy --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@/tmp/trivy-gitlab.tpl" -o gl-container-scanning-report.json $IMAGE cache: diff --git a/docs/docs/advanced/private-registries/index.md b/docs/docs/advanced/private-registries/index.md index 7d5a594cf5b6..7bac7a2742d5 100644 --- a/docs/docs/advanced/private-registries/index.md +++ b/docs/docs/advanced/private-registries/index.md @@ -1,13 +1,30 @@ Trivy can download images from a private registry without the need for installing Docker or any other 3rd party tools. This makes it easy to run within a CI process. -## Credential -To use Trivy with private images, simply install it and provide your credentials: +## Login +You can log in to a private registry using the `trivy auth login` command. +It uses the Docker configuration file (`~/.docker/config.json`) to store the credentials under the hood, and the configuration file path can be configured by `DOCKER_CONFIG` environment variable. + +```shell +$ cat ~/my_password.txt | trivy auth login --username foo --password-stdin ghcr.io +$ trivy image ghcr.io/your/private_image +``` + +## Passing Credentials +You can also provide your credentials when scanning. ```shell $ TRIVY_USERNAME=YOUR_USERNAME TRIVY_PASSWORD=YOUR_PASSWORD trivy image YOUR_PRIVATE_IMAGE ``` +!!! warning + When passing credentials via environment variables or CLI flags, Trivy will attempt to use these credentials for all registries encountered during scanning, regardless of the target registry. + This can potentially lead to unintended credential exposure. + To mitigate this risk: + + 1. Set credentials cautiously and only when necessary. + 2. Prefer using `trivy auth config` to pre-configure credentials with specific registries, which ensures credentials are only sent to appropriate registries. + Trivy also supports providing credentials through CLI flags: ```shell @@ -17,6 +34,7 @@ $ TRIVY_PASSWORD=YOUR_PASSWORD trivy image --username YOUR_USERNAME YOUR_PRIVATE !!! warning The CLI flag `--password` is available, but its use is not recommended for security reasons. + You can also store your credentials in `trivy.yaml`. For more information, please refer to [the documentation](../../references/configuration/config-file.md). @@ -35,15 +53,5 @@ In the example above, Trivy attempts to use two pairs of credentials: Please note that the number of usernames and passwords must be the same. -## docker login -If you have Docker configured locally and have set up the credentials, Trivy can access them. - -```shell -$ docker login ghcr.io -Username: -Password: -$ trivy image ghcr.io/your/private_image -``` - !!! note - `docker login` can be used with any container runtime, such as Podman. + `--password-stdin` doesn't support comma-separated passwords. \ No newline at end of file diff --git a/docs/docs/references/configuration/cli/trivy.md b/docs/docs/references/configuration/cli/trivy.md index 3d8ece9cd0e8..2919e43cbe27 100644 --- a/docs/docs/references/configuration/cli/trivy.md +++ b/docs/docs/references/configuration/cli/trivy.md @@ -43,6 +43,7 @@ trivy [global flags] command [flags] target ### SEE ALSO +* [trivy auth](trivy_auth.md) - Authentication * [trivy clean](trivy_clean.md) - Remove cached files * [trivy config](trivy_config.md) - Scan config files for misconfigurations * [trivy convert](trivy_convert.md) - Convert Trivy JSON report into a different format diff --git a/docs/docs/references/configuration/cli/trivy_auth.md b/docs/docs/references/configuration/cli/trivy_auth.md new file mode 100644 index 000000000000..ba2eaa6a6715 --- /dev/null +++ b/docs/docs/references/configuration/cli/trivy_auth.md @@ -0,0 +1,29 @@ +## trivy auth + +Authentication + +### Options + +``` + -h, --help help for auth +``` + +### Options inherited from parent commands + +``` + --cache-dir string cache directory (default "/path/to/cache") + -c, --config string config path (default "trivy.yaml") + -d, --debug debug mode + --generate-default-config write the default config to trivy-default.yaml + --insecure allow insecure server connections + -q, --quiet suppress progress bar and log output + --timeout duration timeout (default 5m0s) + -v, --version show version +``` + +### SEE ALSO + +* [trivy](trivy.md) - Unified security scanner +* [trivy auth login](trivy_auth_login.md) - Log in to a registry +* [trivy auth logout](trivy_auth_logout.md) - Log out of a registry + diff --git a/docs/docs/references/configuration/cli/trivy_auth_login.md b/docs/docs/references/configuration/cli/trivy_auth_login.md new file mode 100644 index 000000000000..8f2cfdb18abc --- /dev/null +++ b/docs/docs/references/configuration/cli/trivy_auth_login.md @@ -0,0 +1,41 @@ +## trivy auth login + +Log in to a registry + +``` +trivy auth login SERVER [flags] +``` + +### Examples + +``` + # Log in to reg.example.com + cat ~/my_password.txt | trivy auth login --username foo --password-stdin reg.example.com +``` + +### Options + +``` + -h, --help help for login + --password strings password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons. + --password-stdin password from stdin. Comma-separated passwords are not supported. + --username strings username. Comma-separated usernames allowed. +``` + +### Options inherited from parent commands + +``` + --cache-dir string cache directory (default "/path/to/cache") + -c, --config string config path (default "trivy.yaml") + -d, --debug debug mode + --generate-default-config write the default config to trivy-default.yaml + --insecure allow insecure server connections + -q, --quiet suppress progress bar and log output + --timeout duration timeout (default 5m0s) + -v, --version show version +``` + +### SEE ALSO + +* [trivy auth](trivy_auth.md) - Authentication + diff --git a/docs/docs/references/configuration/cli/trivy_auth_logout.md b/docs/docs/references/configuration/cli/trivy_auth_logout.md new file mode 100644 index 000000000000..3a25958001cd --- /dev/null +++ b/docs/docs/references/configuration/cli/trivy_auth_logout.md @@ -0,0 +1,38 @@ +## trivy auth logout + +Log out of a registry + +``` +trivy auth logout SERVER [flags] +``` + +### Examples + +``` + # Log out of reg.example.com + trivy auth logout reg.example.com +``` + +### Options + +``` + -h, --help help for logout +``` + +### Options inherited from parent commands + +``` + --cache-dir string cache directory (default "/path/to/cache") + -c, --config string config path (default "trivy.yaml") + -d, --debug debug mode + --generate-default-config write the default config to trivy-default.yaml + --insecure allow insecure server connections + -q, --quiet suppress progress bar and log output + --timeout duration timeout (default 5m0s) + -v, --version show version +``` + +### SEE ALSO + +* [trivy auth](trivy_auth.md) - Authentication + diff --git a/docs/docs/references/configuration/cli/trivy_config.md b/docs/docs/references/configuration/cli/trivy_config.md index be7854548496..0c279f1e7bf3 100644 --- a/docs/docs/references/configuration/cli/trivy_config.md +++ b/docs/docs/references/configuration/cli/trivy_config.md @@ -39,6 +39,7 @@ trivy config [flags] DIR -o, --output string output file name --output-plugin-arg string [EXPERIMENTAL] output plugin arguments --password strings password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons. + --password-stdin password from stdin. Comma-separated passwords are not supported. --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 diff --git a/docs/docs/references/configuration/cli/trivy_filesystem.md b/docs/docs/references/configuration/cli/trivy_filesystem.md index 0abec4990173..bbd5257d5f5d 100644 --- a/docs/docs/references/configuration/cli/trivy_filesystem.md +++ b/docs/docs/references/configuration/cli/trivy_filesystem.md @@ -68,6 +68,7 @@ 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. + --password-stdin password from stdin. Comma-separated passwords are not supported. --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 diff --git a/docs/docs/references/configuration/cli/trivy_image.md b/docs/docs/references/configuration/cli/trivy_image.md index f9095f041572..779b54f4d5b9 100644 --- a/docs/docs/references/configuration/cli/trivy_image.md +++ b/docs/docs/references/configuration/cli/trivy_image.md @@ -86,6 +86,7 @@ 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. + --password-stdin password from stdin. Comma-separated passwords are not supported. --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 diff --git a/docs/docs/references/configuration/cli/trivy_kubernetes.md b/docs/docs/references/configuration/cli/trivy_kubernetes.md index 99fbc1badaa2..6b8058cc00f0 100644 --- a/docs/docs/references/configuration/cli/trivy_kubernetes.md +++ b/docs/docs/references/configuration/cli/trivy_kubernetes.md @@ -83,6 +83,7 @@ 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. + --password-stdin password from stdin. Comma-separated passwords are not supported. --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) diff --git a/docs/docs/references/configuration/cli/trivy_repository.md b/docs/docs/references/configuration/cli/trivy_repository.md index 821923262dee..190640f5cb2a 100644 --- a/docs/docs/references/configuration/cli/trivy_repository.md +++ b/docs/docs/references/configuration/cli/trivy_repository.md @@ -68,6 +68,7 @@ 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. + --password-stdin password from stdin. Comma-separated passwords are not supported. --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 diff --git a/docs/docs/references/configuration/cli/trivy_rootfs.md b/docs/docs/references/configuration/cli/trivy_rootfs.md index bf2575af23b9..2f37484d0328 100644 --- a/docs/docs/references/configuration/cli/trivy_rootfs.md +++ b/docs/docs/references/configuration/cli/trivy_rootfs.md @@ -70,6 +70,7 @@ 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. + --password-stdin password from stdin. Comma-separated passwords are not supported. --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 diff --git a/docs/docs/references/configuration/cli/trivy_sbom.md b/docs/docs/references/configuration/cli/trivy_sbom.md index 4eaedcf17aa5..55df0959deb6 100644 --- a/docs/docs/references/configuration/cli/trivy_sbom.md +++ b/docs/docs/references/configuration/cli/trivy_sbom.md @@ -48,6 +48,7 @@ trivy sbom [flags] SBOM_PATH -o, --output string output file name --output-plugin-arg string [EXPERIMENTAL] output plugin arguments --password strings password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons. + --password-stdin password from stdin. Comma-separated passwords are not supported. --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 diff --git a/docs/docs/references/configuration/cli/trivy_server.md b/docs/docs/references/configuration/cli/trivy_server.md index b7ada8f2c19b..80eacd43ee4f 100644 --- a/docs/docs/references/configuration/cli/trivy_server.md +++ b/docs/docs/references/configuration/cli/trivy_server.md @@ -30,6 +30,7 @@ trivy server [flags] --module-dir string specify directory to the wasm modules that will be loaded (default "$HOME/.trivy/modules") --no-progress suppress progress bar --password strings password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons. + --password-stdin password from stdin. Comma-separated passwords are not supported. --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 diff --git a/docs/docs/references/configuration/config-file.md b/docs/docs/references/configuration/config-file.md index 9bc9d4351360..ae04978801b3 100644 --- a/docs/docs/references/configuration/config-file.md +++ b/docs/docs/references/configuration/config-file.md @@ -461,6 +461,9 @@ registry: # Same as '--password' password: [] + # Same as '--password-stdin' + password-stdin: false + # Same as '--registry-token' token: "" diff --git a/docs/docs/target/container_image.md b/docs/docs/target/container_image.md index 94acc954a743..6f514db29fb5 100644 --- a/docs/docs/target/container_image.md +++ b/docs/docs/target/container_image.md @@ -297,7 +297,7 @@ Trivy supports registries that comply with the following specifications. - [Docker Registry HTTP API V2](https://docs.docker.com/registry/spec/api/) - [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec) -You can configure credentials with `docker login`. +You can configure credentials with `trivy auth login`. See [here](../advanced/private-registries/index.md) for the detail. ### Tar Files diff --git a/go.mod b/go.mod index d01ce2a7d4c7..1611c8c7080a 100644 --- a/go.mod +++ b/go.mod @@ -43,6 +43,7 @@ require ( github.com/cheggaaa/pb/v3 v3.1.5 github.com/containerd/containerd v1.7.22 github.com/csaf-poc/csaf_distribution/v3 v3.0.0 + github.com/docker/cli v27.2.1+incompatible github.com/docker/docker v27.3.1+incompatible github.com/docker/go-connections v0.5.0 github.com/fatih/color v1.17.0 @@ -210,7 +211,6 @@ require ( github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/dlclark/regexp2 v1.4.0 // indirect - github.com/docker/cli v27.2.1+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect diff --git a/integration/registry_test.go b/integration/registry_test.go index 3831ea9a280e..ce77db5ad74a 100644 --- a/integration/registry_test.go +++ b/integration/registry_test.go @@ -117,6 +117,7 @@ type registryOption struct { Username string Password string RegistryToken bool + AuthLogin bool } func TestRegistry(t *testing.T) { @@ -164,7 +165,6 @@ func TestRegistry(t *testing.T) { imageFile: "testdata/fixtures/images/alpine-310.tar.gz", os: "alpine 3.10.2", option: registryOption{ - AuthURL: authURL, Username: authUsername, Password: authPassword, }, @@ -183,13 +183,24 @@ func TestRegistry(t *testing.T) { }, golden: "testdata/alpine-310.json.golden", }, + { + name: "authenticate with 'trivy auth login'", + imageName: "alpine:3.10", + imageFile: "testdata/fixtures/images/alpine-310.tar.gz", + os: "alpine 3.10.2", + option: registryOption{ + Username: authUsername, + Password: authPassword, + AuthLogin: true, + }, + golden: "testdata/alpine-310.json.golden", + }, { name: "amazonlinux 2", imageName: "amazonlinux:2", imageFile: "testdata/fixtures/images/amazon-2.tar.gz", os: "amazon 2 (Karoo)", option: registryOption{ - AuthURL: authURL, Username: authUsername, Password: authPassword, }, @@ -201,7 +212,6 @@ func TestRegistry(t *testing.T) { imageFile: "testdata/fixtures/images/debian-buster.tar.gz", os: "debian 10.1", option: registryOption{ - AuthURL: authURL, Username: authUsername, Password: authPassword, }, @@ -226,6 +236,7 @@ func TestRegistry(t *testing.T) { require.NoError(t, err) osArgs, err := scan(t, imageRef, baseDir, tt.option) + require.NoError(t, err) // Run Trivy runTest(t, osArgs, tt.golden, "", types.FormatJSON, runOptions{ @@ -262,7 +273,7 @@ func scan(t *testing.T, imageRef name.Reference, baseDir string, opt registryOpt "json", "--image-src", "remote", - "--skip-update", + "--skip-db-update", imageRef.Name(), } @@ -273,14 +284,30 @@ func setupEnv(t *testing.T, imageRef name.Reference, baseDir string, opt registr t.Setenv("TRIVY_INSECURE", "true") if opt.Username != "" && opt.Password != "" { - if opt.RegistryToken { + switch { + case opt.RegistryToken: // Get a registry token in advance token, err := requestRegistryToken(imageRef, baseDir, opt) if err != nil { return err } t.Setenv("TRIVY_REGISTRY_TOKEN", token) - } else { + case opt.AuthLogin: + t.Setenv("DOCKER_CONFIG", t.TempDir()) + err := execute([]string{ + "auth", + "login", + "--username", + opt.Username, + "--password", + opt.Password, + "--insecure", + imageRef.Context().RegistryStr(), + }) + if err != nil { + return err + } + default: t.Setenv("TRIVY_USERNAME", opt.Username) t.Setenv("TRIVY_PASSWORD", opt.Password) } diff --git a/mkdocs.yml b/mkdocs.yml index abe494df9dd9..1d3d6276e2c3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -158,6 +158,10 @@ nav: - Configuration: - CLI: - Overview: docs/references/configuration/cli/trivy.md + - Auth: + - Auth: docs/references/configuration/cli/trivy_auth.md + - Auth Login: docs/references/configuration/cli/trivy_auth_login.md + - Auth Logout: docs/references/configuration/cli/trivy_auth_logout.md - Clean: docs/references/configuration/cli/trivy_clean.md - Config: docs/references/configuration/cli/trivy_config.md - Convert: docs/references/configuration/cli/trivy_convert.md diff --git a/pkg/commands/app.go b/pkg/commands/app.go index bdba2fa12ac7..eec063a3eba3 100644 --- a/pkg/commands/app.go +++ b/pkg/commands/app.go @@ -15,6 +15,7 @@ import ( "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/commands/artifact" + "github.com/aquasecurity/trivy/pkg/commands/auth" "github.com/aquasecurity/trivy/pkg/commands/clean" "github.com/aquasecurity/trivy/pkg/commands/convert" "github.com/aquasecurity/trivy/pkg/commands/server" @@ -99,6 +100,7 @@ func NewApp() *cobra.Command { NewVersionCommand(globalFlags), NewVMCommand(globalFlags), NewCleanCommand(globalFlags), + NewAuthCommand(globalFlags), NewVEXCommand(globalFlags), ) @@ -1233,6 +1235,62 @@ func NewCleanCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { return cmd } +func NewAuthCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { + cmd := &cobra.Command{ + Use: "auth [flags]", + GroupID: groupUtility, + Short: "Authentication", + SilenceErrors: true, + SilenceUsage: true, + } + + loginFlags := &flag.Flags{ + GlobalFlagGroup: globalFlags, + RegistryFlagGroup: flag.NewRegistryFlagGroup(), + } + loginFlags.RegistryFlagGroup.RegistryToken = nil // disable '--registry-token' + loginCmd := &cobra.Command{ + Use: "login SERVER", + Short: "Log in to a registry", + SilenceErrors: true, + SilenceUsage: true, + Example: ` # Log in to reg.example.com + cat ~/my_password.txt | trivy auth login --username foo --password-stdin reg.example.com`, + Args: cobra.ExactArgs(1), + PreRunE: func(cmd *cobra.Command, args []string) error { + if err := loginFlags.Bind(cmd); err != nil { + return xerrors.Errorf("flag bind error: %w", err) + } + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + loginOpts, err := loginFlags.ToOptions(args) + if err != nil { + return xerrors.Errorf("flag error: %w", err) + } + return auth.Login(cmd.Context(), args[0], loginOpts) + }, + } + logoutCmd := &cobra.Command{ + Use: "logout SERVER", + Short: "Log out of a registry", + SilenceErrors: true, + SilenceUsage: true, + Example: ` # Log out of reg.example.com + trivy auth logout reg.example.com`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + return auth.Logout(cmd.Context(), args[0]) + }, + } + loginFlags.AddFlags(loginCmd) + cmd.AddCommand(loginCmd, logoutCmd) + + cmd.SetFlagErrorFunc(flagErrorFunc) + + return cmd +} + func NewVEXCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { vexFlags := &flag.Flags{ GlobalFlagGroup: globalFlags, diff --git a/pkg/commands/auth/run.go b/pkg/commands/auth/run.go new file mode 100644 index 000000000000..7659702f2b7e --- /dev/null +++ b/pkg/commands/auth/run.go @@ -0,0 +1,109 @@ +package auth + +import ( + "context" + "net/http" + "os" + + "github.com/docker/cli/cli/config" + "github.com/docker/cli/cli/config/types" + "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/google/go-containerregistry/pkg/v1/remote/transport" + "golang.org/x/xerrors" + + "github.com/aquasecurity/trivy/pkg/flag" + "github.com/aquasecurity/trivy/pkg/log" +) + +func Login(ctx context.Context, registry string, opts flag.Options) error { + if len(opts.Credentials) == 0 { + return xerrors.New("username and password required") + } else if len(opts.Credentials) > 1 { + return xerrors.New("multiple credentials are not allowed") + } + + reg, err := parseRegistry(registry, opts) + if err != nil { + return xerrors.Errorf("failed to parse registry: %w", err) + } + serverAddress := reg.Name() + + // Validate the credential + _, err = transport.NewWithContext(ctx, reg, &authn.Basic{ + Username: opts.Credentials[0].Username, + Password: opts.Credentials[0].Password, + }, httpTransport(opts), []string{reg.Scope(transport.PullScope)}) + if err != nil { + return xerrors.Errorf("failed to authenticate: %w", err) + } + + cf, err := config.Load(os.Getenv("DOCKER_CONFIG")) + if err != nil { + return xerrors.Errorf("failed to load docker config: %w", err) + } + creds := cf.GetCredentialsStore(serverAddress) + if serverAddress == name.DefaultRegistry { + serverAddress = authn.DefaultAuthKey + } + if err := creds.Store(types.AuthConfig{ + ServerAddress: serverAddress, + Username: opts.Credentials[0].Username, + Password: opts.Credentials[0].Password, + }); err != nil { + return xerrors.Errorf("failed to store credentials: %w", err) + } + + if err := cf.Save(); err != nil { + return xerrors.Errorf("failed to save docker config: %w", err) + } + log.Info("Login succeeded", log.FilePath(cf.Filename), log.String("username", opts.Credentials[0].Username)) + return nil +} + +func Logout(_ context.Context, registry string) error { + reg, err := parseRegistry(registry, flag.Options{}) + if err != nil { + return xerrors.Errorf("failed to parse registry: %w", err) + } + serverAddress := reg.Name() + + cf, err := config.Load(os.Getenv("DOCKER_CONFIG")) + if err != nil { + return xerrors.Errorf("failed to load docker config: %w", err) + } + creds := cf.GetCredentialsStore(serverAddress) + if serverAddress == name.DefaultRegistry { + serverAddress = authn.DefaultAuthKey + } + if err := creds.Erase(serverAddress); err != nil { + return xerrors.Errorf("failed to delete credentials: %w", err) + } + + if err := cf.Save(); err != nil { + return xerrors.Errorf("failed to save docker config: %w", err) + } + log.Info("Logged out", log.FilePath(cf.Filename)) + return nil +} + +func parseRegistry(registry string, opts flag.Options) (name.Registry, error) { + var nameOpts []name.Option + if opts.Insecure { + nameOpts = append(nameOpts, name.Insecure) + } + reg, err := name.NewRegistry(registry, nameOpts...) + if err != nil { + return name.Registry{}, xerrors.Errorf("failed to parse registry: %w", err) + } + return reg, nil +} + +func httpTransport(opts flag.Options) *http.Transport { + tr := remote.DefaultTransport.(*http.Transport).Clone() + if opts.Insecure { + tr.TLSClientConfig.InsecureSkipVerify = true + } + return tr +} diff --git a/pkg/commands/auth/run_test.go b/pkg/commands/auth/run_test.go new file mode 100644 index 000000000000..2b2df244031f --- /dev/null +++ b/pkg/commands/auth/run_test.go @@ -0,0 +1,142 @@ +package auth_test + +import ( + "context" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/samber/lo" + "github.com/stretchr/testify/require" + + testauth "github.com/aquasecurity/testdocker/auth" + "github.com/aquasecurity/testdocker/registry" + "github.com/aquasecurity/trivy/pkg/commands/auth" + "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/flag" +) + +func TestLogin(t *testing.T) { + type args struct { + registry string + opts flag.Options + } + tests := []struct { + name string + args args + wantErr string + }{ + { + name: "single credential", + args: args{ + opts: flag.Options{ + RegistryOptions: flag.RegistryOptions{ + Credentials: []types.Credential{ + { + Username: "user", + Password: "pass", + }, + }, + }, + }, + }, + }, + { + name: "multiple credentials", + args: args{ + opts: flag.Options{ + RegistryOptions: flag.RegistryOptions{ + Credentials: []types.Credential{ + { + Username: "user1", + Password: "pass1", + }, + { + Username: "user2", + Password: "pass2", + }, + }, + }, + }, + }, + wantErr: "multiple credentials are not allowed", + }, + { + name: "no credentials", + args: args{ + registry: "auth.test", + opts: flag.Options{}, + }, + wantErr: "username and password required", + }, + { + name: "invalid registry", + args: args{ + registry: "aaa://invalid.test", + opts: flag.Options{ + RegistryOptions: flag.RegistryOptions{ + Credentials: []types.Credential{ + { + Username: "user", + Password: "pass", + }, + }, + }, + }, + }, + wantErr: "registries must be valid RFC 3986 URI authorities", + }, + } + + tr := registry.NewDockerRegistry(registry.Option{ + Auth: testauth.Auth{ + User: "user", + Password: "pass", + }, + }) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Set the DOCKER_CONFIG environment variable to a temporary directory + // so that the test does not interfere with the user's configuration. + t.Setenv("DOCKER_CONFIG", filepath.Join(t.TempDir(), "config.json")) + + reg := lo.Ternary(tt.args.registry == "", strings.TrimPrefix(tr.URL, "http://"), tt.args.registry) + err := auth.Login(context.Background(), reg, tt.args.opts) + if tt.wantErr != "" { + require.ErrorContains(t, err, tt.wantErr) + return + } + require.NoError(t, err) + }) + } +} + +func TestLogout(t *testing.T) { + // Set the DOCKER_CONFIG environment variable to a temporary directory + // so that the test does not interfere with the user's configuration. + tmpDir := t.TempDir() + t.Setenv("DOCKER_CONFIG", tmpDir) + + t.Run("success", func(t *testing.T) { + configFile := filepath.Join(tmpDir, "config.json") + err := os.WriteFile(configFile, []byte(`{"auths": {"auth.test": {"auth": "dXNlcjpwYXNz"}}}`), 0600) + require.NoError(t, err) + + err = auth.Logout(context.Background(), "auth.test") + require.NoError(t, err) + b, err := os.ReadFile(configFile) + require.NoError(t, err) + require.JSONEq(t, `{"auths": {}}`, string(b)) + }) + t.Run("not found", func(t *testing.T) { + err := auth.Logout(context.Background(), "notfound.test") + require.NoError(t, err) // Return an error if "credsStore" is "osxkeychain". + }) + + t.Run("invalid registry", func(t *testing.T) { + err := auth.Logout(context.Background(), "aaa://invalid.test") + require.ErrorContains(t, err, "registries must be valid RFC 3986 URI authorities") + }) +} diff --git a/pkg/flag/registry_flags.go b/pkg/flag/registry_flags.go index 552eaf4276d6..9c03a07b8872 100644 --- a/pkg/flag/registry_flags.go +++ b/pkg/flag/registry_flags.go @@ -1,6 +1,8 @@ package flag import ( + "io" + "os" "strings" "golang.org/x/xerrors" @@ -19,6 +21,11 @@ var ( ConfigName: "registry.password", Usage: "password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons.", } + PasswordStdinFlag = Flag[bool]{ + Name: "password-stdin", + ConfigName: "registry.password-stdin", + Usage: "password from stdin. Comma-separated passwords are not supported.", + } RegistryTokenFlag = Flag[string]{ Name: "registry-token", ConfigName: "registry.token", @@ -29,6 +36,7 @@ var ( type RegistryFlagGroup struct { Username *Flag[[]string] Password *Flag[[]string] + PasswordStdin *Flag[bool] RegistryToken *Flag[string] } @@ -41,6 +49,7 @@ func NewRegistryFlagGroup() *RegistryFlagGroup { return &RegistryFlagGroup{ Username: UsernameFlag.Clone(), Password: PasswordFlag.Clone(), + PasswordStdin: PasswordStdinFlag.Clone(), RegistryToken: RegistryTokenFlag.Clone(), } } @@ -53,6 +62,7 @@ func (f *RegistryFlagGroup) Flags() []Flagger { return []Flagger{ f.Username, f.Password, + f.PasswordStdin, f.RegistryToken, } } @@ -65,8 +75,19 @@ func (f *RegistryFlagGroup) ToOptions() (RegistryOptions, error) { var credentials []types.Credential users := f.Username.Value() passwords := f.Password.Value() + if f.PasswordStdin.Value() { + if len(passwords) != 0 { + return RegistryOptions{}, xerrors.New("'--password' and '--password-stdin' can't be used at the same time") + } + contents, err := io.ReadAll(os.Stdin) + if err != nil { + return RegistryOptions{}, xerrors.Errorf("failed to read from stdin: %w", err) + } + // "--password-stdin" doesn't support comma-separated passwords + passwords = []string{strings.TrimRight(string(contents), "\r\n")} + } if len(users) != len(passwords) { - return RegistryOptions{}, xerrors.New("the length of usernames and passwords must match") + return RegistryOptions{}, xerrors.New("the number of usernames and passwords must match") } for i, user := range users { credentials = append(credentials, types.Credential{ From 672e886aed152ae0f09a16941706746f3053ca94 Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Thu, 10 Oct 2024 15:02:06 +0400 Subject: [PATCH 43/94] fix(cli): `clean --all` deletes only relevant dirs (#7704) Signed-off-by: knqyf263 --- pkg/commands/clean/run.go | 15 +++++---------- pkg/commands/clean/run_test.go | 26 +++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/pkg/commands/clean/run.go b/pkg/commands/clean/run.go index c60227360d19..8dd83519422f 100644 --- a/pkg/commands/clean/run.go +++ b/pkg/commands/clean/run.go @@ -2,7 +2,6 @@ package clean import ( "context" - "os" "golang.org/x/xerrors" @@ -25,7 +24,11 @@ func Run(ctx context.Context, opts flag.Options) error { } if opts.CleanAll { - return cleanAll(ctx, opts) + opts.CleanScanCache = true + opts.CleanVulnerabilityDB = true + opts.CleanJavaDB = true + opts.CleanChecksBundle = true + opts.CleanVEXRepositories = true } if opts.CleanScanCache { @@ -60,14 +63,6 @@ func Run(ctx context.Context, opts flag.Options) error { return nil } -func cleanAll(ctx context.Context, opts flag.Options) error { - log.InfoContext(ctx, "Removing all caches...") - if err := os.RemoveAll(opts.CacheDir); err != nil { - return xerrors.Errorf("failed to remove the directory (%s) : %w", opts.CacheDir, err) - } - return nil -} - func cleanScanCache(ctx context.Context, opts flag.Options) error { log.InfoContext(ctx, "Removing scan cache...") c, cleanup, err := cache.New(opts.CacheOpts()) diff --git a/pkg/commands/clean/run_test.go b/pkg/commands/clean/run_test.go index 9b301d238219..32e4110aba97 100644 --- a/pkg/commands/clean/run_test.go +++ b/pkg/commands/clean/run_test.go @@ -28,7 +28,12 @@ func TestRun(t *testing.T) { }, wantErr: false, checkFunc: func(t *testing.T, dir string) { - assert.NoDirExists(t, dir) + assert.NoDirExists(t, filepath.Join(dir, "fanal")) + assert.NoDirExists(t, filepath.Join(dir, "db")) + assert.NoDirExists(t, filepath.Join(dir, "java-db")) + assert.NoDirExists(t, filepath.Join(dir, "policy")) + assert.NoDirExists(t, filepath.Join(dir, "vex")) + assert.DirExists(t, dir) }, }, { @@ -42,6 +47,7 @@ func TestRun(t *testing.T) { assert.DirExists(t, filepath.Join(dir, "db")) assert.DirExists(t, filepath.Join(dir, "java-db")) assert.DirExists(t, filepath.Join(dir, "policy")) + assert.DirExists(t, filepath.Join(dir, "vex")) }, }, { @@ -55,6 +61,7 @@ func TestRun(t *testing.T) { assert.DirExists(t, filepath.Join(dir, "fanal")) assert.DirExists(t, filepath.Join(dir, "java-db")) assert.DirExists(t, filepath.Join(dir, "policy")) + assert.DirExists(t, filepath.Join(dir, "vex")) }, }, { @@ -68,6 +75,7 @@ func TestRun(t *testing.T) { assert.DirExists(t, filepath.Join(dir, "fanal")) assert.DirExists(t, filepath.Join(dir, "db")) assert.DirExists(t, filepath.Join(dir, "policy")) + assert.DirExists(t, filepath.Join(dir, "vex")) }, }, { @@ -81,6 +89,21 @@ func TestRun(t *testing.T) { assert.DirExists(t, filepath.Join(dir, "fanal")) assert.DirExists(t, filepath.Join(dir, "db")) assert.DirExists(t, filepath.Join(dir, "java-db")) + assert.DirExists(t, filepath.Join(dir, "vex")) + }, + }, + { + name: "clean vex repositories", + cleanOpts: flag.CleanOptions{ + CleanVEXRepositories: true, + }, + wantErr: false, + checkFunc: func(t *testing.T, dir string) { + assert.DirExists(t, filepath.Join(dir, "policy")) + assert.DirExists(t, filepath.Join(dir, "fanal")) + assert.DirExists(t, filepath.Join(dir, "db")) + assert.DirExists(t, filepath.Join(dir, "java-db")) + assert.NoDirExists(t, filepath.Join(dir, "vex")) }, }, { @@ -127,6 +150,7 @@ func createTestFiles(t *testing.T, dir string) { "db", "java-db", "policy", + "vex", } for _, subdir := range subdirs { err := os.MkdirAll(filepath.Join(dir, subdir), 0755) From c78f45b4a71a0fb92232aad7594351466125bee2 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Fri, 11 Oct 2024 10:40:13 +0600 Subject: [PATCH 44/94] refactor(misconf): introduce generic scanner (#7515) Signed-off-by: nikpivkin --- pkg/iac/scanners/dockerfile/parser/parser.go | 64 +---- .../scanners/dockerfile/parser/parser_test.go | 13 +- pkg/iac/scanners/dockerfile/scanner.go | 108 +-------- pkg/iac/scanners/dockerfile/scanner_test.go | 7 +- pkg/iac/scanners/generic/scanner.go | 220 +++++++++++++++++ pkg/iac/scanners/generic/scanner_test.go | 223 ++++++++++++++++++ pkg/iac/scanners/json/parser/parser.go | 65 ----- pkg/iac/scanners/json/parser/parser_test.go | 51 ---- pkg/iac/scanners/json/scanner.go | 113 --------- pkg/iac/scanners/json/scanner_test.go | 80 ------- pkg/iac/scanners/toml/parser/parser.go | 65 ----- pkg/iac/scanners/toml/parser/parser_test.go | 55 ----- pkg/iac/scanners/toml/scanner.go | 111 --------- pkg/iac/scanners/toml/scanner_test.go | 85 ------- pkg/iac/scanners/yaml/parser/parser.go | 86 ------- pkg/iac/scanners/yaml/parser/parser_test.go | 150 ------------ pkg/iac/scanners/yaml/scanner.go | 113 --------- pkg/iac/scanners/yaml/scanner_test.go | 88 ------- pkg/misconf/scanner.go | 7 +- 19 files changed, 469 insertions(+), 1235 deletions(-) create mode 100644 pkg/iac/scanners/generic/scanner.go create mode 100644 pkg/iac/scanners/generic/scanner_test.go delete mode 100644 pkg/iac/scanners/json/parser/parser.go delete mode 100644 pkg/iac/scanners/json/parser/parser_test.go delete mode 100644 pkg/iac/scanners/json/scanner.go delete mode 100644 pkg/iac/scanners/json/scanner_test.go delete mode 100644 pkg/iac/scanners/toml/parser/parser.go delete mode 100644 pkg/iac/scanners/toml/parser/parser_test.go delete mode 100644 pkg/iac/scanners/toml/scanner.go delete mode 100644 pkg/iac/scanners/toml/scanner_test.go delete mode 100644 pkg/iac/scanners/yaml/parser/parser.go delete mode 100644 pkg/iac/scanners/yaml/parser/parser_test.go delete mode 100644 pkg/iac/scanners/yaml/scanner.go delete mode 100644 pkg/iac/scanners/yaml/scanner_test.go diff --git a/pkg/iac/scanners/dockerfile/parser/parser.go b/pkg/iac/scanners/dockerfile/parser/parser.go index e92116ae3079..128d9515e8b1 100644 --- a/pkg/iac/scanners/dockerfile/parser/parser.go +++ b/pkg/iac/scanners/dockerfile/parser/parser.go @@ -4,76 +4,26 @@ import ( "context" "fmt" "io" - "io/fs" - "path/filepath" "strings" "github.com/moby/buildkit/frontend/dockerfile/instructions" "github.com/moby/buildkit/frontend/dockerfile/parser" "github.com/aquasecurity/trivy/pkg/iac/providers/dockerfile" - "github.com/aquasecurity/trivy/pkg/log" ) -type Parser struct { - logger *log.Logger -} - -// New creates a new Dockerfile parser -func New() *Parser { - return &Parser{ - logger: log.WithPrefix("dockerfile parser"), - } -} - -func (p *Parser) ParseFS(ctx context.Context, target fs.FS, path string) (map[string]*dockerfile.Dockerfile, error) { - - files := make(map[string]*dockerfile.Dockerfile) - if err := fs.WalkDir(target, filepath.ToSlash(path), func(path string, entry fs.DirEntry, err error) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - if err != nil { - return err - } - if entry.IsDir() { - return nil - } - - df, err := p.ParseFile(ctx, target, path) - if err != nil { - p.logger.Error("Failed to parse Dockerfile", log.FilePath(path), log.Err(err)) - return nil - } - files[path] = df - return nil - }); err != nil { - return nil, err - } - return files, nil -} - -// ParseFile parses Dockerfile content from the provided filesystem path. -func (p *Parser) ParseFile(_ context.Context, fsys fs.FS, path string) (*dockerfile.Dockerfile, error) { - f, err := fsys.Open(filepath.ToSlash(path)) - if err != nil { - return nil, err - } - defer func() { _ = f.Close() }() - return p.parse(path, f) -} - -func (p *Parser) parse(path string, r io.Reader) (*dockerfile.Dockerfile, error) { +func Parse(_ context.Context, r io.Reader, path string) (any, error) { parsed, err := parser.Parse(r) if err != nil { return nil, fmt.Errorf("dockerfile parse error: %w", err) } - var parsedFile dockerfile.Dockerfile - var stage dockerfile.Stage - var stageIndex int + var ( + parsedFile dockerfile.Dockerfile + stage dockerfile.Stage + stageIndex int + ) + fromValue := "args" for _, child := range parsed.AST.Children { child.Value = strings.ToLower(child.Value) diff --git a/pkg/iac/scanners/dockerfile/parser/parser_test.go b/pkg/iac/scanners/dockerfile/parser/parser_test.go index 764cb3a0e091..ad1acf193bf3 100644 --- a/pkg/iac/scanners/dockerfile/parser/parser_test.go +++ b/pkg/iac/scanners/dockerfile/parser/parser_test.go @@ -1,11 +1,15 @@ -package parser +package parser_test import ( + "context" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/aquasecurity/trivy/pkg/iac/providers/dockerfile" + "github.com/aquasecurity/trivy/pkg/iac/scanners/dockerfile/parser" ) func Test_Parser(t *testing.T) { @@ -15,12 +19,13 @@ RUN make /app CMD python /app/app.py ` - df, err := New().parse("Dockerfile", strings.NewReader(input)) + res, err := parser.Parse(context.TODO(), strings.NewReader(input), "Dockerfile") require.NoError(t, err) - assert.Len(t, df.Stages, 1) + df, ok := res.(*dockerfile.Dockerfile) + require.True(t, ok) - require.Len(t, df.Stages, 1) + assert.Len(t, df.Stages, 1) assert.Equal(t, "ubuntu:18.04", df.Stages[0].Name) commands := df.Stages[0].Commands diff --git a/pkg/iac/scanners/dockerfile/scanner.go b/pkg/iac/scanners/dockerfile/scanner.go index 1694f28d814a..5637410945eb 100644 --- a/pkg/iac/scanners/dockerfile/scanner.go +++ b/pkg/iac/scanners/dockerfile/scanner.go @@ -1,114 +1,12 @@ package dockerfile import ( - "context" - "io/fs" - "sync" - - "github.com/aquasecurity/trivy/pkg/iac/framework" - "github.com/aquasecurity/trivy/pkg/iac/rego" - "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners" "github.com/aquasecurity/trivy/pkg/iac/scanners/dockerfile/parser" + "github.com/aquasecurity/trivy/pkg/iac/scanners/generic" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" "github.com/aquasecurity/trivy/pkg/iac/types" - "github.com/aquasecurity/trivy/pkg/log" ) -var _ scanners.FSScanner = (*Scanner)(nil) -var _ options.ConfigurableScanner = (*Scanner)(nil) - -type Scanner struct { - mu sync.Mutex - logger *log.Logger - parser *parser.Parser - regoScanner *rego.Scanner - options []options.ScannerOption -} - -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetRegoOnly(bool) {} -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} - -func (s *Scanner) Name() string { - return "Dockerfile" -} - -func NewScanner(opts ...options.ScannerOption) *Scanner { - s := &Scanner{ - options: opts, - logger: log.WithPrefix("dockerfile scanner"), - } - for _, opt := range opts { - opt(s) - } - s.parser = parser.New() - return s -} - -func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, path string) (scan.Results, error) { - - files, err := s.parser.ParseFS(ctx, fsys, path) - if err != nil { - return nil, err - } - - if len(files) == 0 { - return nil, nil - } - - var inputs []rego.Input - for path, dfile := range files { - inputs = append(inputs, rego.Input{ - Path: path, - FS: fsys, - Contents: dfile.ToRego(), - }) - } - - results, err := s.scanRego(ctx, fsys, inputs...) - if err != nil { - return nil, err - } - return results, nil -} - -func (s *Scanner) ScanFile(ctx context.Context, fsys fs.FS, path string) (scan.Results, error) { - dockerfile, err := s.parser.ParseFile(ctx, fsys, path) - if err != nil { - return nil, err - } - s.logger.Debug("Scanning", log.FilePath(path)) - return s.scanRego(ctx, fsys, rego.Input{ - Path: path, - Contents: dockerfile.ToRego(), - }) -} - -func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { - s.mu.Lock() - defer s.mu.Unlock() - if s.regoScanner != nil { - return s.regoScanner, nil - } - - regoScanner := rego.NewScanner(types.SourceDockerfile, s.options...) - if err := regoScanner.LoadPolicies(srcFS); err != nil { - return nil, err - } - s.regoScanner = regoScanner - return regoScanner, nil -} - -func (s *Scanner) scanRego(ctx context.Context, srcFS fs.FS, inputs ...rego.Input) (scan.Results, error) { - regoScanner, err := s.initRegoScanner(srcFS) - if err != nil { - return nil, err - } - results, err := regoScanner.ScanInput(ctx, inputs...) - if err != nil { - return nil, err - } - results.SetSourceAndFilesystem("", srcFS, false) - return results, nil +func NewScanner(opts ...options.ScannerOption) *generic.GenericScanner { + return generic.NewScanner("Dockerfile", types.SourceDockerfile, generic.ParseFunc(parser.Parse), opts...) } diff --git a/pkg/iac/scanners/dockerfile/scanner_test.go b/pkg/iac/scanners/dockerfile/scanner_test.go index 2872df1e4ef6..e8c66b27db08 100644 --- a/pkg/iac/scanners/dockerfile/scanner_test.go +++ b/pkg/iac/scanners/dockerfile/scanner_test.go @@ -1,4 +1,4 @@ -package dockerfile +package dockerfile_test import ( "bytes" @@ -13,6 +13,7 @@ import ( "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/rego/schemas" "github.com/aquasecurity/trivy/pkg/iac/scan" + "github.com/aquasecurity/trivy/pkg/iac/scanners/dockerfile" ) const DS006PolicyWithDockerfileSchema = `# METADATA @@ -219,7 +220,7 @@ USER root "/rules/rule.rego": DS006LegacyWithOldStyleMetadata, }) - scanner := NewScanner(rego.WithPolicyDirs("rules")) + scanner := dockerfile.NewScanner(rego.WithPolicyDirs("rules")) results, err := scanner.ScanFS(context.TODO(), fs, "code") require.NoError(t, err) @@ -563,7 +564,7 @@ COPY --from=dep /binary /` var traceBuf bytes.Buffer - scanner := NewScanner( + scanner := dockerfile.NewScanner( rego.WithPolicyDirs("rules"), rego.WithEmbeddedLibraries(true), rego.WithTrace(&traceBuf), diff --git a/pkg/iac/scanners/generic/scanner.go b/pkg/iac/scanners/generic/scanner.go new file mode 100644 index 000000000000..5a36709d9a04 --- /dev/null +++ b/pkg/iac/scanners/generic/scanner.go @@ -0,0 +1,220 @@ +package generic + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "io/fs" + "path/filepath" + "strings" + "sync" + + "github.com/BurntSushi/toml" + "gopkg.in/yaml.v3" + + "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" + "github.com/aquasecurity/trivy/pkg/iac/scan" + "github.com/aquasecurity/trivy/pkg/iac/scanners/options" + "github.com/aquasecurity/trivy/pkg/iac/types" + "github.com/aquasecurity/trivy/pkg/log" +) + +func NewJsonScanner(opts ...options.ScannerOption) *GenericScanner { + return NewScanner("JSON", types.SourceJSON, ParseFunc(parseJson), opts...) +} + +func NewYamlScanner(opts ...options.ScannerOption) *GenericScanner { + return NewScanner("YAML", types.SourceYAML, ParseFunc(parseYaml), opts...) +} + +func NewTomlScanner(opts ...options.ScannerOption) *GenericScanner { + return NewScanner("TOML", types.SourceTOML, ParseFunc(parseTOML), opts...) +} + +type configParser interface { + Parse(ctx context.Context, r io.Reader, path string) (any, error) +} + +// GenericScanner is a scanner that scans a file as is without processing it +type GenericScanner struct { + mu sync.Mutex + name string + source types.Source + logger *log.Logger + options []options.ScannerOption + regoScanner *rego.Scanner + + parser configParser +} + +type ParseFunc func(ctx context.Context, r io.Reader, path string) (any, error) + +func (f ParseFunc) Parse(ctx context.Context, r io.Reader, path string) (any, error) { + return f(ctx, r, path) +} + +func NewScanner(name string, source types.Source, parser configParser, opts ...options.ScannerOption) *GenericScanner { + s := &GenericScanner{ + name: name, + options: opts, + source: source, + logger: log.WithPrefix(fmt.Sprintf("%s scanner", source)), + parser: parser, + } + + for _, opt := range opts { + opt(s) + } + + return s +} + +func (s *GenericScanner) Name() string { + return s.name +} + +func (s *GenericScanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (scan.Results, error) { + fileset, err := s.parseFS(ctx, fsys, dir) + if err != nil { + return nil, err + } + + if len(fileset) == 0 { + return nil, nil + } + + var inputs []rego.Input + for path, val := range fileset { + switch v := val.(type) { + case interface{ ToRego() any }: + inputs = append(inputs, rego.Input{ + Path: path, + Contents: v.ToRego(), + FS: fsys, + }) + case []any: + for _, file := range v { + inputs = append(inputs, rego.Input{ + Path: path, + Contents: file, + FS: fsys, + }) + } + default: + inputs = append(inputs, rego.Input{ + Path: path, + Contents: v, + FS: fsys, + }) + } + } + + regoScanner, err := s.initRegoScanner(fsys) + if err != nil { + return nil, err + } + + s.logger.Debug("Scanning files...", log.Int("count", len(inputs))) + results, err := regoScanner.ScanInput(ctx, inputs...) + if err != nil { + return nil, err + } + results.SetSourceAndFilesystem("", fsys, false) + return results, nil +} + +func (s *GenericScanner) parseFS(ctx context.Context, fsys fs.FS, path string) (map[string]any, error) { + files := make(map[string]any) + if err := fs.WalkDir(fsys, filepath.ToSlash(path), func(path string, entry fs.DirEntry, err error) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + if err != nil { + return err + } + if entry.IsDir() { + return nil + } + + f, err := fsys.Open(filepath.ToSlash(path)) + if err != nil { + return err + } + defer f.Close() + + df, err := s.parser.Parse(ctx, f, path) + if err != nil { + s.logger.Error("Failed to parse file", log.FilePath(path), log.Err(err)) + return nil + } + files[path] = df + return nil + }); err != nil { + return nil, err + } + return files, nil +} + +func (s *GenericScanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { + s.mu.Lock() + defer s.mu.Unlock() + if s.regoScanner != nil { + return s.regoScanner, nil + } + regoScanner := rego.NewScanner(s.source, s.options...) + if err := regoScanner.LoadPolicies(srcFS); err != nil { + return nil, err + } + s.regoScanner = regoScanner + return regoScanner, nil +} + +func (*GenericScanner) SetRegoOnly(bool) {} +func (*GenericScanner) SetIncludeDeprecatedChecks(bool) {} +func (*GenericScanner) SetFrameworks([]framework.Framework) {} + +func parseJson(ctx context.Context, r io.Reader, _ string) (any, error) { + var target any + if err := json.NewDecoder(r).Decode(&target); err != nil { + return nil, err + } + return target, nil +} + +func parseYaml(ctx context.Context, r io.Reader, _ string) (any, error) { + contents, err := io.ReadAll(r) + if err != nil { + return nil, err + } + + var results []any + + marker := "\n---\n" + altMarker := "\r\n---\r\n" + if bytes.Contains(contents, []byte(altMarker)) { + marker = altMarker + } + + for _, partial := range strings.Split(string(contents), marker) { + var target any + if err := yaml.Unmarshal([]byte(partial), &target); err != nil { + return nil, err + } + results = append(results, target) + } + + return results, nil +} + +func parseTOML(ctx context.Context, r io.Reader, _ string) (any, error) { + var target any + if _, err := toml.NewDecoder(r).Decode(&target); err != nil { + return nil, err + } + return target, nil +} diff --git a/pkg/iac/scanners/generic/scanner_test.go b/pkg/iac/scanners/generic/scanner_test.go new file mode 100644 index 000000000000..46d0eef1653a --- /dev/null +++ b/pkg/iac/scanners/generic/scanner_test.go @@ -0,0 +1,223 @@ +package generic_test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/aquasecurity/trivy/internal/testutil" + "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" + "github.com/aquasecurity/trivy/pkg/iac/scan" + "github.com/aquasecurity/trivy/pkg/iac/scanners/generic" +) + +func TestJsonScanner(t *testing.T) { + fsys := testutil.CreateFS(t, map[string]string{ + "/code/data.json": `{ "x": { "y": 123, "z": ["a", "b", "c"]}}`, + "/rules/rule.rego": `package builtin.json.lol + +__rego_metadata__ := { + "id": "ABC123", + "avd_id": "AVD-AB-0123", + "title": "title", + "short_code": "short", + "severity": "CRITICAL", + "type": "JSON Check", + "description": "description", + "recommended_actions": "actions", + "url": "https://example.com", +} + +__rego_input__ := { + "combine": false, + "selector": [{"type": "json"}], +} + +deny[res] { + input.x.y == 123 + res := { + "msg": "oh no", + "startline": 1, + "endline": 2, + } +} + +`, + }) + + scanner := generic.NewJsonScanner(rego.WithPolicyDirs("rules")) + + results, err := scanner.ScanFS(context.TODO(), fsys, "code") + require.NoError(t, err) + + require.Len(t, results.GetFailed(), 1) + + assert.Equal(t, scan.Rule{ + AVDID: "AVD-AB-0123", + Aliases: []string{"ABC123"}, + ShortCode: "short", + Summary: "title", + Explanation: "description", + Impact: "", + Resolution: "actions", + Provider: "json", + Service: "general", + Links: []string{"https://example.com"}, + Severity: "CRITICAL", + Terraform: &scan.EngineMetadata{}, + CloudFormation: &scan.EngineMetadata{}, + CustomChecks: scan.CustomChecks{ + Terraform: (*scan.TerraformCustomCheck)(nil), + }, + RegoPackage: "data.builtin.json.lol", + Frameworks: map[framework.Framework][]string{ + framework.Default: {}, + }, + }, results.GetFailed()[0].Rule()) +} + +func TestYamlScanner(t *testing.T) { + fsys := testutil.CreateFS(t, map[string]string{ + "/code/data.yaml": `--- +x: + y: 123 + z: + - a + - b + - c +`, + "/rules/rule.rego": `package builtin.yaml.lol + +__rego_metadata__ := { + "id": "ABC123", + "avd_id": "AVD-AB-0123", + "title": "title", + "short_code": "short", + "severity": "CRITICAL", + "type": "YAML Check", + "description": "description", + "recommended_actions": "actions", + "url": "https://example.com", +} + +__rego_input__ := { + "combine": false, + "selector": [{"type": "yaml"}], +} + +deny[res] { + input.x.y == 123 + res := { + "msg": "oh no", + "startline": 1, + "endline": 2, + } +} + +`, + }) + + scanner := generic.NewYamlScanner(rego.WithPolicyDirs("rules")) + + results, err := scanner.ScanFS(context.TODO(), fsys, "code") + require.NoError(t, err) + + require.Len(t, results.GetFailed(), 1) + + assert.Equal(t, scan.Rule{ + AVDID: "AVD-AB-0123", + Aliases: []string{"ABC123"}, + ShortCode: "short", + Summary: "title", + Explanation: "description", + Impact: "", + Resolution: "actions", + Provider: "yaml", + Service: "general", + Links: []string{"https://example.com"}, + Severity: "CRITICAL", + Terraform: &scan.EngineMetadata{}, + CloudFormation: &scan.EngineMetadata{}, + CustomChecks: scan.CustomChecks{ + Terraform: (*scan.TerraformCustomCheck)(nil)}, + RegoPackage: "data.builtin.yaml.lol", + Frameworks: map[framework.Framework][]string{ + framework.Default: {}, + }, + }, + results.GetFailed()[0].Rule(), + ) +} + +func TestTomlParser(t *testing.T) { + fsys := testutil.CreateFS(t, map[string]string{ + "/code/code.toml": ` +[x] +y = 123 +z = ["a", "b", "c"] +`, + "/rules/rule.rego": `package builtin.toml.lol + +__rego_metadata__ := { + "id": "ABC123", + "avd_id": "AVD-AB-0123", + "title": "title", + "short_code": "short", + "severity": "CRITICAL", + "type": "TOML Check", + "description": "description", + "recommended_actions": "actions", + "url": "https://example.com", +} + +__rego_input__ := { + "combine": false, + "selector": [{"type": "toml"}], +} + +deny[res] { + input.x.y == 123 + res := { + "msg": "oh no", + "startline": 1, + "endline": 2, + } +} + +`, + }) + + scanner := generic.NewTomlScanner(rego.WithPolicyDirs("rules")) + + results, err := scanner.ScanFS(context.TODO(), fsys, "code") + require.NoError(t, err) + + require.Len(t, results.GetFailed(), 1) + + assert.Equal(t, scan.Rule{ + AVDID: "AVD-AB-0123", + Aliases: []string{"ABC123"}, + ShortCode: "short", + Summary: "title", + Explanation: "description", + Impact: "", + Resolution: "actions", + Provider: "toml", + Service: "general", + Links: []string{"https://example.com"}, + Severity: "CRITICAL", + Terraform: &scan.EngineMetadata{}, + CloudFormation: &scan.EngineMetadata{}, + CustomChecks: scan.CustomChecks{ + Terraform: (*scan.TerraformCustomCheck)(nil)}, + RegoPackage: "data.builtin.toml.lol", + Frameworks: map[framework.Framework][]string{ + framework.Default: {}, + }, + }, + results.GetFailed()[0].Rule(), + ) +} diff --git a/pkg/iac/scanners/json/parser/parser.go b/pkg/iac/scanners/json/parser/parser.go deleted file mode 100644 index c97e54b40bd9..000000000000 --- a/pkg/iac/scanners/json/parser/parser.go +++ /dev/null @@ -1,65 +0,0 @@ -package parser - -import ( - "context" - "encoding/json" - "io/fs" - "path/filepath" - - "github.com/aquasecurity/trivy/pkg/log" -) - -type Parser struct { - logger *log.Logger -} - -// New creates a new parser -func New() *Parser { - return &Parser{ - logger: log.WithPrefix("json parser"), - } -} - -func (p *Parser) ParseFS(ctx context.Context, target fs.FS, path string) (map[string]any, error) { - - files := make(map[string]any) - if err := fs.WalkDir(target, filepath.ToSlash(path), func(path string, entry fs.DirEntry, err error) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - if err != nil { - return err - } - if entry.IsDir() { - return nil - } - - df, err := p.ParseFile(ctx, target, path) - if err != nil { - p.logger.Error("Parse error", log.FilePath(path), log.Err(err)) - return nil - } - - files[path] = df - return nil - }); err != nil { - return nil, err - } - return files, nil -} - -// ParseFile parses Dockerfile content from the provided filesystem path. -func (p *Parser) ParseFile(_ context.Context, fsys fs.FS, path string) (any, error) { - f, err := fsys.Open(filepath.ToSlash(path)) - if err != nil { - return nil, err - } - defer func() { _ = f.Close() }() - var target any - if err := json.NewDecoder(f).Decode(&target); err != nil { - return nil, err - } - return target, nil -} diff --git a/pkg/iac/scanners/json/parser/parser_test.go b/pkg/iac/scanners/json/parser/parser_test.go deleted file mode 100644 index a47868fad0ed..000000000000 --- a/pkg/iac/scanners/json/parser/parser_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package parser - -import ( - "context" - "testing" - - "github.com/liamg/memoryfs" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func Test_Parser(t *testing.T) { - input := `{ "x": { "y": 123, "z": ["a", "b", "c"]}}` - - memfs := memoryfs.New() - err := memfs.WriteFile("something.json", []byte(input), 0644) - require.NoError(t, err) - - data, err := New().ParseFile(context.TODO(), memfs, "something.json") - require.NoError(t, err) - - msi, ok := data.(map[string]any) - require.True(t, ok) - - xObj, ok := msi["x"] - require.True(t, ok) - - xMsi, ok := xObj.(map[string]any) - require.True(t, ok) - - yRaw, ok := xMsi["y"] - require.True(t, ok) - - y, ok := yRaw.(float64) - require.True(t, ok) - - assert.InEpsilon(t, 123.0, y, 0.0001) - - zRaw, ok := xMsi["z"] - require.True(t, ok) - - z, ok := zRaw.([]any) - require.True(t, ok) - - require.Len(t, z, 3) - - assert.Equal(t, "a", z[0]) - assert.Equal(t, "b", z[1]) - assert.Equal(t, "c", z[2]) - -} diff --git a/pkg/iac/scanners/json/scanner.go b/pkg/iac/scanners/json/scanner.go deleted file mode 100644 index f46f9cc56bc9..000000000000 --- a/pkg/iac/scanners/json/scanner.go +++ /dev/null @@ -1,113 +0,0 @@ -package json - -import ( - "context" - "io/fs" - "sync" - - "github.com/aquasecurity/trivy/pkg/iac/framework" - "github.com/aquasecurity/trivy/pkg/iac/rego" - "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners" - "github.com/aquasecurity/trivy/pkg/iac/scanners/json/parser" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" - "github.com/aquasecurity/trivy/pkg/iac/types" - "github.com/aquasecurity/trivy/pkg/log" -) - -var _ scanners.FSScanner = (*Scanner)(nil) -var _ options.ConfigurableScanner = (*Scanner)(nil) - -type Scanner struct { - mu sync.Mutex - logger *log.Logger - parser *parser.Parser - regoScanner *rego.Scanner - options []options.ScannerOption -} - -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetRegoOnly(bool) {} -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} - -func NewScanner(opts ...options.ScannerOption) *Scanner { - s := &Scanner{ - options: opts, - logger: log.WithPrefix("json scanner"), - parser: parser.New(), - } - for _, opt := range opts { - opt(s) - } - return s -} - -func (s *Scanner) Name() string { - return "JSON" -} - -func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, path string) (scan.Results, error) { - - files, err := s.parser.ParseFS(ctx, fsys, path) - if err != nil { - return nil, err - } - - if len(files) == 0 { - return nil, nil - } - - var inputs []rego.Input - for path, file := range files { - inputs = append(inputs, rego.Input{ - Path: path, - FS: fsys, - Contents: file, - }) - } - - results, err := s.scanRego(ctx, fsys, inputs...) - if err != nil { - return nil, err - } - return results, nil -} - -func (s *Scanner) ScanFile(ctx context.Context, fsys fs.FS, path string) (scan.Results, error) { - parsed, err := s.parser.ParseFile(ctx, fsys, path) - if err != nil { - return nil, err - } - s.logger.Debug("Scanning", log.FilePath(path)) - return s.scanRego(ctx, fsys, rego.Input{ - Path: path, - Contents: parsed, - }) -} - -func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { - s.mu.Lock() - defer s.mu.Unlock() - if s.regoScanner != nil { - return s.regoScanner, nil - } - regoScanner := rego.NewScanner(types.SourceJSON, s.options...) - if err := regoScanner.LoadPolicies(srcFS); err != nil { - return nil, err - } - s.regoScanner = regoScanner - return regoScanner, nil -} - -func (s *Scanner) scanRego(ctx context.Context, srcFS fs.FS, inputs ...rego.Input) (scan.Results, error) { - regoScanner, err := s.initRegoScanner(srcFS) - if err != nil { - return nil, err - } - results, err := regoScanner.ScanInput(ctx, inputs...) - if err != nil { - return nil, err - } - results.SetSourceAndFilesystem("", srcFS, false) - return results, nil -} diff --git a/pkg/iac/scanners/json/scanner_test.go b/pkg/iac/scanners/json/scanner_test.go deleted file mode 100644 index 6656f70b2e25..000000000000 --- a/pkg/iac/scanners/json/scanner_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package json - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/aquasecurity/trivy/internal/testutil" - "github.com/aquasecurity/trivy/pkg/iac/framework" - "github.com/aquasecurity/trivy/pkg/iac/rego" - "github.com/aquasecurity/trivy/pkg/iac/scan" -) - -func Test_BasicScan(t *testing.T) { - - fs := testutil.CreateFS(t, map[string]string{ - "/code/data.json": `{ "x": { "y": 123, "z": ["a", "b", "c"]}}`, - "/rules/rule.rego": `package builtin.json.lol - -__rego_metadata__ := { - "id": "ABC123", - "avd_id": "AVD-AB-0123", - "title": "title", - "short_code": "short", - "severity": "CRITICAL", - "type": "JSON Check", - "description": "description", - "recommended_actions": "actions", - "url": "https://example.com", -} - -__rego_input__ := { - "combine": false, - "selector": [{"type": "json"}], -} - -deny[res] { - input.x.y == 123 - res := { - "msg": "oh no", - "startline": 1, - "endline": 2, - } -} - -`, - }) - - scanner := NewScanner(rego.WithPolicyDirs("rules")) - - results, err := scanner.ScanFS(context.TODO(), fs, "code") - require.NoError(t, err) - - require.Len(t, results.GetFailed(), 1) - - assert.Equal(t, scan.Rule{ - AVDID: "AVD-AB-0123", - Aliases: []string{"ABC123"}, - ShortCode: "short", - Summary: "title", - Explanation: "description", - Impact: "", - Resolution: "actions", - Provider: "json", - Service: "general", - Links: []string{"https://example.com"}, - Severity: "CRITICAL", - Terraform: &scan.EngineMetadata{}, - CloudFormation: &scan.EngineMetadata{}, - CustomChecks: scan.CustomChecks{ - Terraform: (*scan.TerraformCustomCheck)(nil), - }, - RegoPackage: "data.builtin.json.lol", - Frameworks: map[framework.Framework][]string{ - framework.Default: {}, - }, - }, results.GetFailed()[0].Rule()) -} diff --git a/pkg/iac/scanners/toml/parser/parser.go b/pkg/iac/scanners/toml/parser/parser.go deleted file mode 100644 index 95444389d74d..000000000000 --- a/pkg/iac/scanners/toml/parser/parser.go +++ /dev/null @@ -1,65 +0,0 @@ -package parser - -import ( - "context" - "io/fs" - "path/filepath" - - "github.com/BurntSushi/toml" - - "github.com/aquasecurity/trivy/pkg/log" -) - -type Parser struct { - logger *log.Logger -} - -// New creates a new parser -func New() *Parser { - return &Parser{ - logger: log.WithPrefix("toml parser"), - } -} - -func (p *Parser) ParseFS(ctx context.Context, target fs.FS, path string) (map[string]any, error) { - - files := make(map[string]any) - if err := fs.WalkDir(target, filepath.ToSlash(path), func(path string, entry fs.DirEntry, err error) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - if err != nil { - return err - } - if entry.IsDir() { - return nil - } - - df, err := p.ParseFile(ctx, target, path) - if err != nil { - p.logger.Error("Parse error", log.FilePath(path), log.Err(err)) - return nil - } - files[path] = df - return nil - }); err != nil { - return nil, err - } - return files, nil -} - -// ParseFile parses toml content from the provided filesystem path. -func (p *Parser) ParseFile(_ context.Context, fsys fs.FS, path string) (any, error) { - f, err := fsys.Open(filepath.ToSlash(path)) - if err != nil { - return nil, err - } - defer func() { _ = f.Close() }() - var target any - if _, err := toml.NewDecoder(f).Decode(&target); err != nil { - return nil, err - } - return target, nil -} diff --git a/pkg/iac/scanners/toml/parser/parser_test.go b/pkg/iac/scanners/toml/parser/parser_test.go deleted file mode 100644 index 1c9e9bdc341e..000000000000 --- a/pkg/iac/scanners/toml/parser/parser_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package parser - -import ( - "context" - "testing" - - "github.com/liamg/memoryfs" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func Test_Parser(t *testing.T) { - input := ` -[x] -y = 123 -z = ["a", "b", "c"] -` - - memfs := memoryfs.New() - err := memfs.WriteFile("something.yaml", []byte(input), 0644) - require.NoError(t, err) - - data, err := New().ParseFile(context.TODO(), memfs, "something.yaml") - require.NoError(t, err) - - msi, ok := data.(map[string]any) - require.True(t, ok) - - xObj, ok := msi["x"] - require.True(t, ok) - - xMsi, ok := xObj.(map[string]any) - require.True(t, ok) - - yRaw, ok := xMsi["y"] - require.True(t, ok) - - y, ok := yRaw.(int64) - require.True(t, ok) - - assert.Equal(t, int64(123), y) - - zRaw, ok := xMsi["z"] - require.True(t, ok) - - z, ok := zRaw.([]any) - require.True(t, ok) - - require.Len(t, z, 3) - - assert.Equal(t, "a", z[0]) - assert.Equal(t, "b", z[1]) - assert.Equal(t, "c", z[2]) - -} diff --git a/pkg/iac/scanners/toml/scanner.go b/pkg/iac/scanners/toml/scanner.go deleted file mode 100644 index 216d0b1f9697..000000000000 --- a/pkg/iac/scanners/toml/scanner.go +++ /dev/null @@ -1,111 +0,0 @@ -package toml - -import ( - "context" - "io/fs" - "sync" - - "github.com/aquasecurity/trivy/pkg/iac/framework" - "github.com/aquasecurity/trivy/pkg/iac/rego" - "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" - "github.com/aquasecurity/trivy/pkg/iac/scanners/toml/parser" - "github.com/aquasecurity/trivy/pkg/iac/types" - "github.com/aquasecurity/trivy/pkg/log" -) - -var _ options.ConfigurableScanner = (*Scanner)(nil) - -type Scanner struct { - mu sync.Mutex - logger *log.Logger - options []options.ScannerOption - parser *parser.Parser - regoScanner *rego.Scanner -} - -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetRegoOnly(bool) {} -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} - -func (s *Scanner) Name() string { - return "TOML" -} - -func NewScanner(opts ...options.ScannerOption) *Scanner { - s := &Scanner{ - options: opts, - logger: log.WithPrefix("toml scanner"), - } - for _, opt := range opts { - opt(s) - } - s.parser = parser.New() - return s -} - -func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, path string) (scan.Results, error) { - - files, err := s.parser.ParseFS(ctx, fsys, path) - if err != nil { - return nil, err - } - - if len(files) == 0 { - return nil, nil - } - - var inputs []rego.Input - for path, file := range files { - inputs = append(inputs, rego.Input{ - Path: path, - Contents: file, - FS: fsys, - }) - } - - results, err := s.scanRego(ctx, fsys, inputs...) - if err != nil { - return nil, err - } - return results, nil -} - -func (s *Scanner) ScanFile(ctx context.Context, fsys fs.FS, path string) (scan.Results, error) { - parsed, err := s.parser.ParseFile(ctx, fsys, path) - if err != nil { - return nil, err - } - s.logger.Debug("Scanning", log.FilePath(path)) - return s.scanRego(ctx, fsys, rego.Input{ - Path: path, - Contents: parsed, - }) -} - -func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { - s.mu.Lock() - defer s.mu.Unlock() - if s.regoScanner != nil { - return s.regoScanner, nil - } - regoScanner := rego.NewScanner(types.SourceTOML, s.options...) - if err := regoScanner.LoadPolicies(srcFS); err != nil { - return nil, err - } - s.regoScanner = regoScanner - return regoScanner, nil -} - -func (s *Scanner) scanRego(ctx context.Context, srcFS fs.FS, inputs ...rego.Input) (scan.Results, error) { - regoScanner, err := s.initRegoScanner(srcFS) - if err != nil { - return nil, err - } - results, err := regoScanner.ScanInput(ctx, inputs...) - if err != nil { - return nil, err - } - results.SetSourceAndFilesystem("", srcFS, false) - return results, nil -} diff --git a/pkg/iac/scanners/toml/scanner_test.go b/pkg/iac/scanners/toml/scanner_test.go deleted file mode 100644 index ea5819448288..000000000000 --- a/pkg/iac/scanners/toml/scanner_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package toml - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/aquasecurity/trivy/internal/testutil" - "github.com/aquasecurity/trivy/pkg/iac/framework" - "github.com/aquasecurity/trivy/pkg/iac/rego" - "github.com/aquasecurity/trivy/pkg/iac/scan" -) - -func Test_BasicScan(t *testing.T) { - - fs := testutil.CreateFS(t, map[string]string{ - "/code/code.toml": ` -[x] -y = 123 -z = ["a", "b", "c"] -`, - "/rules/rule.rego": `package builtin.toml.lol - -__rego_metadata__ := { - "id": "ABC123", - "avd_id": "AVD-AB-0123", - "title": "title", - "short_code": "short", - "severity": "CRITICAL", - "type": "TOML Check", - "description": "description", - "recommended_actions": "actions", - "url": "https://example.com", -} - -__rego_input__ := { - "combine": false, - "selector": [{"type": "toml"}], -} - -deny[res] { - input.x.y == 123 - res := { - "msg": "oh no", - "startline": 1, - "endline": 2, - } -} - -`, - }) - - scanner := NewScanner(rego.WithPolicyDirs("rules")) - - results, err := scanner.ScanFS(context.TODO(), fs, "code") - require.NoError(t, err) - - require.Len(t, results.GetFailed(), 1) - - assert.Equal(t, scan.Rule{ - AVDID: "AVD-AB-0123", - Aliases: []string{"ABC123"}, - ShortCode: "short", - Summary: "title", - Explanation: "description", - Impact: "", - Resolution: "actions", - Provider: "toml", - Service: "general", - Links: []string{"https://example.com"}, - Severity: "CRITICAL", - Terraform: &scan.EngineMetadata{}, - CloudFormation: &scan.EngineMetadata{}, - CustomChecks: scan.CustomChecks{ - Terraform: (*scan.TerraformCustomCheck)(nil)}, - RegoPackage: "data.builtin.toml.lol", - Frameworks: map[framework.Framework][]string{ - framework.Default: {}, - }, - }, - results.GetFailed()[0].Rule(), - ) -} diff --git a/pkg/iac/scanners/yaml/parser/parser.go b/pkg/iac/scanners/yaml/parser/parser.go deleted file mode 100644 index 9b1f026ae248..000000000000 --- a/pkg/iac/scanners/yaml/parser/parser.go +++ /dev/null @@ -1,86 +0,0 @@ -package parser - -import ( - "bytes" - "context" - "io" - "io/fs" - "path/filepath" - - "gopkg.in/yaml.v3" - - "github.com/aquasecurity/trivy/pkg/log" -) - -type Parser struct { - logger *log.Logger -} - -// New creates a new YAML parser -func New() *Parser { - return &Parser{ - logger: log.WithPrefix("yaml parser"), - } -} - -func (p *Parser) ParseFS(ctx context.Context, target fs.FS, path string) (map[string][]any, error) { - - files := make(map[string][]any) - if err := fs.WalkDir(target, filepath.ToSlash(path), func(path string, entry fs.DirEntry, err error) error { - - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - if err != nil { - return err - } - if entry.IsDir() { - return nil - } - - df, err := p.ParseFile(ctx, target, path) - if err != nil { - p.logger.Error("Parse error", log.FilePath(path), log.Err(err)) - return nil - } - files[path] = df - return nil - }); err != nil { - return nil, err - } - return files, nil -} - -// ParseFile parses yaml content from the provided filesystem path. -func (p *Parser) ParseFile(_ context.Context, fsys fs.FS, path string) ([]any, error) { - f, err := fsys.Open(filepath.ToSlash(path)) - if err != nil { - return nil, err - } - defer func() { _ = f.Close() }() - - contents, err := io.ReadAll(f) - if err != nil { - return nil, err - } - - var results []any - - marker := []byte("\n---\n") - altMarker := []byte("\r\n---\r\n") - if bytes.Contains(contents, altMarker) { - marker = altMarker - } - - for _, partial := range bytes.Split(contents, marker) { - var target any - if err := yaml.Unmarshal(partial, &target); err != nil { - return nil, err - } - results = append(results, target) - } - - return results, nil -} diff --git a/pkg/iac/scanners/yaml/parser/parser_test.go b/pkg/iac/scanners/yaml/parser/parser_test.go deleted file mode 100644 index f7817d5990fa..000000000000 --- a/pkg/iac/scanners/yaml/parser/parser_test.go +++ /dev/null @@ -1,150 +0,0 @@ -package parser - -import ( - "context" - "testing" - - "github.com/liamg/memoryfs" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func Test_Parser(t *testing.T) { - input := `--- -x: - y: 123 - z: - - a - - b - - c -` - - memfs := memoryfs.New() - err := memfs.WriteFile("something.yaml", []byte(input), 0644) - require.NoError(t, err) - - data, err := New().ParseFile(context.TODO(), memfs, "something.yaml") - require.NoError(t, err) - - assert.Len(t, data, 1) - - msi, ok := data[0].(map[string]any) - require.True(t, ok) - - xObj, ok := msi["x"] - require.True(t, ok) - - xMsi, ok := xObj.(map[string]any) - require.True(t, ok) - - yRaw, ok := xMsi["y"] - require.True(t, ok) - - y, ok := yRaw.(int) - require.True(t, ok) - - assert.Equal(t, 123, y) - - zRaw, ok := xMsi["z"] - require.True(t, ok) - - z, ok := zRaw.([]any) - require.True(t, ok) - - require.Len(t, z, 3) - - assert.Equal(t, "a", z[0]) - assert.Equal(t, "b", z[1]) - assert.Equal(t, "c", z[2]) - -} - -func Test_Parser_WithSeparatedContent(t *testing.T) { - input := `--- -x: - y: 123 - z: - - a - - b - - c ---- -x: - y: 456 - z: - - x - - y - - z -` - - memfs := memoryfs.New() - err := memfs.WriteFile("something.yaml", []byte(input), 0644) - require.NoError(t, err) - - data, err := New().ParseFile(context.TODO(), memfs, "something.yaml") - require.NoError(t, err) - - assert.Len(t, data, 2) - - { - msi, ok := data[0].(map[string]any) - require.True(t, ok) - - xObj, ok := msi["x"] - require.True(t, ok) - - xMsi, ok := xObj.(map[string]any) - require.True(t, ok) - - yRaw, ok := xMsi["y"] - require.True(t, ok) - - y, ok := yRaw.(int) - require.True(t, ok) - - assert.Equal(t, 123, y) - - zRaw, ok := xMsi["z"] - require.True(t, ok) - - z, ok := zRaw.([]any) - require.True(t, ok) - - require.Len(t, z, 3) - - assert.Equal(t, "a", z[0]) - assert.Equal(t, "b", z[1]) - assert.Equal(t, "c", z[2]) - } - - { - msi, ok := data[1].(map[string]any) - require.True(t, ok) - - xObj, ok := msi["x"] - require.True(t, ok) - - xMsi, ok := xObj.(map[string]any) - require.True(t, ok) - - yRaw, ok := xMsi["y"] - require.True(t, ok) - - y, ok := yRaw.(int) - require.True(t, ok) - - assert.Equal(t, 456, y) - - zRaw, ok := xMsi["z"] - require.True(t, ok) - - z, ok := zRaw.([]any) - require.True(t, ok) - - require.Len(t, z, 3) - - assert.Equal(t, "x", z[0]) - assert.Equal(t, "y", z[1]) - assert.Equal(t, "z", z[2]) - } - -} diff --git a/pkg/iac/scanners/yaml/scanner.go b/pkg/iac/scanners/yaml/scanner.go deleted file mode 100644 index 565d10df1f83..000000000000 --- a/pkg/iac/scanners/yaml/scanner.go +++ /dev/null @@ -1,113 +0,0 @@ -package yaml - -import ( - "context" - "io/fs" - "sync" - - "github.com/aquasecurity/trivy/pkg/iac/framework" - "github.com/aquasecurity/trivy/pkg/iac/rego" - "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" - "github.com/aquasecurity/trivy/pkg/iac/scanners/yaml/parser" - "github.com/aquasecurity/trivy/pkg/iac/types" - "github.com/aquasecurity/trivy/pkg/log" -) - -var _ options.ConfigurableScanner = (*Scanner)(nil) - -type Scanner struct { - mu sync.Mutex - options []options.ScannerOption - logger *log.Logger - parser *parser.Parser - regoScanner *rego.Scanner -} - -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetRegoOnly(bool) {} -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} - -func (s *Scanner) Name() string { - return "YAML" -} - -func NewScanner(opts ...options.ScannerOption) *Scanner { - s := &Scanner{ - options: opts, - logger: log.WithPrefix("yaml scanner"), - parser: parser.New(), - } - for _, opt := range opts { - opt(s) - } - return s -} - -func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, path string) (scan.Results, error) { - - fileset, err := s.parser.ParseFS(ctx, fsys, path) - if err != nil { - return nil, err - } - - if len(fileset) == 0 { - return nil, nil - } - - var inputs []rego.Input - for path, files := range fileset { - for _, file := range files { - inputs = append(inputs, rego.Input{ - Path: path, - Contents: file, - FS: fsys, - }) - } - } - - results, err := s.scanRego(ctx, fsys, inputs...) - if err != nil { - return nil, err - } - return results, nil -} - -func (s *Scanner) ScanFile(ctx context.Context, fsys fs.FS, path string) (scan.Results, error) { - parsed, err := s.parser.ParseFile(ctx, fsys, path) - if err != nil { - return nil, err - } - s.logger.Debug("Scanning", log.String("path", path)) - return s.scanRego(ctx, fsys, rego.Input{ - Path: path, - Contents: parsed, - }) -} - -func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { - s.mu.Lock() - defer s.mu.Unlock() - if s.regoScanner != nil { - return s.regoScanner, nil - } - regoScanner := rego.NewScanner(types.SourceYAML, s.options...) - if err := regoScanner.LoadPolicies(srcFS); err != nil { - return nil, err - } - s.regoScanner = regoScanner - return regoScanner, nil -} - -func (s *Scanner) scanRego(ctx context.Context, srcFS fs.FS, inputs ...rego.Input) (scan.Results, error) { - regoScanner, err := s.initRegoScanner(srcFS) - if err != nil { - return nil, err - } - results, err := regoScanner.ScanInput(ctx, inputs...) - if err != nil { - return nil, err - } - results.SetSourceAndFilesystem("", srcFS, false) - return results, nil -} diff --git a/pkg/iac/scanners/yaml/scanner_test.go b/pkg/iac/scanners/yaml/scanner_test.go deleted file mode 100644 index b7c4ec623887..000000000000 --- a/pkg/iac/scanners/yaml/scanner_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package yaml - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/aquasecurity/trivy/internal/testutil" - "github.com/aquasecurity/trivy/pkg/iac/framework" - "github.com/aquasecurity/trivy/pkg/iac/rego" - "github.com/aquasecurity/trivy/pkg/iac/scan" -) - -func Test_BasicScan(t *testing.T) { - - fs := testutil.CreateFS(t, map[string]string{ - "/code/data.yaml": `--- -x: - y: 123 - z: - - a - - b - - c -`, - "/rules/rule.rego": `package builtin.yaml.lol - -__rego_metadata__ := { - "id": "ABC123", - "avd_id": "AVD-AB-0123", - "title": "title", - "short_code": "short", - "severity": "CRITICAL", - "type": "YAML Check", - "description": "description", - "recommended_actions": "actions", - "url": "https://example.com", -} - -__rego_input__ := { - "combine": false, - "selector": [{"type": "yaml"}], -} - -deny[res] { - input.x.y == 123 - res := { - "msg": "oh no", - "startline": 1, - "endline": 2, - } -} - -`, - }) - - scanner := NewScanner(rego.WithPolicyDirs("rules")) - - results, err := scanner.ScanFS(context.TODO(), fs, "code") - require.NoError(t, err) - - require.Len(t, results.GetFailed(), 1) - - assert.Equal(t, scan.Rule{ - AVDID: "AVD-AB-0123", - Aliases: []string{"ABC123"}, - ShortCode: "short", - Summary: "title", - Explanation: "description", - Impact: "", - Resolution: "actions", - Provider: "yaml", - Service: "general", - Links: []string{"https://example.com"}, - Severity: "CRITICAL", - Terraform: &scan.EngineMetadata{}, - CloudFormation: &scan.EngineMetadata{}, - CustomChecks: scan.CustomChecks{ - Terraform: (*scan.TerraformCustomCheck)(nil)}, - RegoPackage: "data.builtin.yaml.lol", - Frameworks: map[framework.Framework][]string{ - framework.Default: {}, - }, - }, - results.GetFailed()[0].Rule(), - ) -} diff --git a/pkg/misconf/scanner.go b/pkg/misconf/scanner.go index 7bec3ed6fe14..04fc28bc5296 100644 --- a/pkg/misconf/scanner.go +++ b/pkg/misconf/scanner.go @@ -24,14 +24,13 @@ import ( cfscanner "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation" cfparser "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation/parser" dfscanner "github.com/aquasecurity/trivy/pkg/iac/scanners/dockerfile" + "github.com/aquasecurity/trivy/pkg/iac/scanners/generic" "github.com/aquasecurity/trivy/pkg/iac/scanners/helm" - jsonscanner "github.com/aquasecurity/trivy/pkg/iac/scanners/json" k8sscanner "github.com/aquasecurity/trivy/pkg/iac/scanners/kubernetes" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform" tfprawscanner "github.com/aquasecurity/trivy/pkg/iac/scanners/terraformplan/snapshot" tfpjsonscanner "github.com/aquasecurity/trivy/pkg/iac/scanners/terraformplan/tfjson" - yamlscanner "github.com/aquasecurity/trivy/pkg/iac/scanners/yaml" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/mapfs" @@ -118,9 +117,9 @@ func NewScanner(t detection.FileType, opt ScannerOption) (*Scanner, error) { case detection.FileTypeTerraformPlanSnapshot: scanner = tfprawscanner.New(opts...) case detection.FileTypeYAML: - scanner = yamlscanner.NewScanner(opts...) + scanner = generic.NewYamlScanner(opts...) case detection.FileTypeJSON: - scanner = jsonscanner.NewScanner(opts...) + scanner = generic.NewJsonScanner(opts...) default: return nil, xerrors.Errorf("unknown file type: %s", t) } From 31aa20ab90d52dd6cbc364fe0ff257b59cf02187 Mon Sep 17 00:00:00 2001 From: Simon Deziel Date: Mon, 14 Oct 2024 00:45:56 -0400 Subject: [PATCH 45/94] docs: apt-transport-https is a transitional package (#7678) Signed-off-by: Simon Deziel --- docs/getting-started/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index 61f6e42871bb..fd8b19366e86 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -34,7 +34,7 @@ In this section you will find an aggregation of the different ways to install Tr Add repository setting to `/etc/apt/sources.list.d`. ``` bash - sudo apt-get install wget apt-transport-https gnupg + sudo apt-get install wget gnupg wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | sudo tee -a /etc/apt/sources.list.d/trivy.list sudo apt-get update From 633a7abeea4287899392a24f2705f96dfeb7e312 Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Tue, 15 Oct 2024 15:24:10 +0400 Subject: [PATCH 46/94] feat(cli): rename `trivy auth` to `trivy registry` (#7727) Signed-off-by: knqyf263 --- contrib/Trivy.gitlab-ci.yml | 2 +- docs/docs/advanced/private-registries/index.md | 6 +++--- docs/docs/references/configuration/cli/trivy.md | 2 +- .../cli/{trivy_auth.md => trivy_registry.md} | 10 +++++----- .../{trivy_auth_login.md => trivy_registry_login.md} | 8 ++++---- ...trivy_auth_logout.md => trivy_registry_logout.md} | 8 ++++---- docs/docs/target/container_image.md | 2 +- integration/registry_test.go | 4 ++-- mkdocs.yml | 8 ++++---- pkg/commands/app.go | 12 ++++++------ 10 files changed, 31 insertions(+), 31 deletions(-) rename docs/docs/references/configuration/cli/{trivy_auth.md => trivy_registry.md} (73%) rename docs/docs/references/configuration/cli/{trivy_auth_login.md => trivy_registry_login.md} (81%) rename docs/docs/references/configuration/cli/{trivy_auth_logout.md => trivy_registry_logout.md} (80%) diff --git a/contrib/Trivy.gitlab-ci.yml b/contrib/Trivy.gitlab-ci.yml index a62e26301a20..f91588240346 100644 --- a/contrib/Trivy.gitlab-ci.yml +++ b/contrib/Trivy.gitlab-ci.yml @@ -14,7 +14,7 @@ Trivy_container_scanning: - apk add --no-cache curl docker-cli - curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin ${TRIVY_VERSION} - curl -sSL -o /tmp/trivy-gitlab.tpl https://github.com/aquasecurity/trivy/raw/${TRIVY_VERSION}/contrib/gitlab.tpl - - trivy auth login --username "$CI_REGISTRY_USER" --password "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + - trivy registry login --username "$CI_REGISTRY_USER" --password "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - trivy --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@/tmp/trivy-gitlab.tpl" -o gl-container-scanning-report.json $IMAGE cache: diff --git a/docs/docs/advanced/private-registries/index.md b/docs/docs/advanced/private-registries/index.md index 7bac7a2742d5..e40f2f8f7230 100644 --- a/docs/docs/advanced/private-registries/index.md +++ b/docs/docs/advanced/private-registries/index.md @@ -2,11 +2,11 @@ Trivy can download images from a private registry without the need for installin This makes it easy to run within a CI process. ## Login -You can log in to a private registry using the `trivy auth login` command. +You can log in to a private registry using the `trivy registry login` command. It uses the Docker configuration file (`~/.docker/config.json`) to store the credentials under the hood, and the configuration file path can be configured by `DOCKER_CONFIG` environment variable. ```shell -$ cat ~/my_password.txt | trivy auth login --username foo --password-stdin ghcr.io +$ cat ~/my_password.txt | trivy registry login --username foo --password-stdin ghcr.io $ trivy image ghcr.io/your/private_image ``` @@ -23,7 +23,7 @@ $ TRIVY_USERNAME=YOUR_USERNAME TRIVY_PASSWORD=YOUR_PASSWORD trivy image YOUR_PRI To mitigate this risk: 1. Set credentials cautiously and only when necessary. - 2. Prefer using `trivy auth config` to pre-configure credentials with specific registries, which ensures credentials are only sent to appropriate registries. + 2. Prefer using `trivy registry login` to pre-configure credentials with specific registries, which ensures credentials are only sent to appropriate registries. Trivy also supports providing credentials through CLI flags: diff --git a/docs/docs/references/configuration/cli/trivy.md b/docs/docs/references/configuration/cli/trivy.md index 2919e43cbe27..0f4faaecde0c 100644 --- a/docs/docs/references/configuration/cli/trivy.md +++ b/docs/docs/references/configuration/cli/trivy.md @@ -43,7 +43,6 @@ trivy [global flags] command [flags] target ### SEE ALSO -* [trivy auth](trivy_auth.md) - Authentication * [trivy clean](trivy_clean.md) - Remove cached files * [trivy config](trivy_config.md) - Scan config files for misconfigurations * [trivy convert](trivy_convert.md) - Convert Trivy JSON report into a different format @@ -52,6 +51,7 @@ trivy [global flags] command [flags] target * [trivy kubernetes](trivy_kubernetes.md) - [EXPERIMENTAL] Scan kubernetes cluster * [trivy module](trivy_module.md) - Manage modules * [trivy plugin](trivy_plugin.md) - Manage plugins +* [trivy registry](trivy_registry.md) - Manage registry authentication * [trivy repository](trivy_repository.md) - Scan a repository * [trivy rootfs](trivy_rootfs.md) - Scan rootfs * [trivy sbom](trivy_sbom.md) - Scan SBOM for vulnerabilities and licenses diff --git a/docs/docs/references/configuration/cli/trivy_auth.md b/docs/docs/references/configuration/cli/trivy_registry.md similarity index 73% rename from docs/docs/references/configuration/cli/trivy_auth.md rename to docs/docs/references/configuration/cli/trivy_registry.md index ba2eaa6a6715..4a42cea3f4df 100644 --- a/docs/docs/references/configuration/cli/trivy_auth.md +++ b/docs/docs/references/configuration/cli/trivy_registry.md @@ -1,11 +1,11 @@ -## trivy auth +## trivy registry -Authentication +Manage registry authentication ### Options ``` - -h, --help help for auth + -h, --help help for registry ``` ### Options inherited from parent commands @@ -24,6 +24,6 @@ Authentication ### SEE ALSO * [trivy](trivy.md) - Unified security scanner -* [trivy auth login](trivy_auth_login.md) - Log in to a registry -* [trivy auth logout](trivy_auth_logout.md) - Log out of a registry +* [trivy registry login](trivy_registry_login.md) - Log in to a registry +* [trivy registry logout](trivy_registry_logout.md) - Log out of a registry diff --git a/docs/docs/references/configuration/cli/trivy_auth_login.md b/docs/docs/references/configuration/cli/trivy_registry_login.md similarity index 81% rename from docs/docs/references/configuration/cli/trivy_auth_login.md rename to docs/docs/references/configuration/cli/trivy_registry_login.md index 8f2cfdb18abc..6e963b3ca9f4 100644 --- a/docs/docs/references/configuration/cli/trivy_auth_login.md +++ b/docs/docs/references/configuration/cli/trivy_registry_login.md @@ -1,16 +1,16 @@ -## trivy auth login +## trivy registry login Log in to a registry ``` -trivy auth login SERVER [flags] +trivy registry login SERVER [flags] ``` ### Examples ``` # Log in to reg.example.com - cat ~/my_password.txt | trivy auth login --username foo --password-stdin reg.example.com + cat ~/my_password.txt | trivy registry login --username foo --password-stdin reg.example.com ``` ### Options @@ -37,5 +37,5 @@ trivy auth login SERVER [flags] ### SEE ALSO -* [trivy auth](trivy_auth.md) - Authentication +* [trivy registry](trivy_registry.md) - Manage registry authentication diff --git a/docs/docs/references/configuration/cli/trivy_auth_logout.md b/docs/docs/references/configuration/cli/trivy_registry_logout.md similarity index 80% rename from docs/docs/references/configuration/cli/trivy_auth_logout.md rename to docs/docs/references/configuration/cli/trivy_registry_logout.md index 3a25958001cd..b3da44c5fe92 100644 --- a/docs/docs/references/configuration/cli/trivy_auth_logout.md +++ b/docs/docs/references/configuration/cli/trivy_registry_logout.md @@ -1,16 +1,16 @@ -## trivy auth logout +## trivy registry logout Log out of a registry ``` -trivy auth logout SERVER [flags] +trivy registry logout SERVER [flags] ``` ### Examples ``` # Log out of reg.example.com - trivy auth logout reg.example.com + trivy registry logout reg.example.com ``` ### Options @@ -34,5 +34,5 @@ trivy auth logout SERVER [flags] ### SEE ALSO -* [trivy auth](trivy_auth.md) - Authentication +* [trivy registry](trivy_registry.md) - Manage registry authentication diff --git a/docs/docs/target/container_image.md b/docs/docs/target/container_image.md index 6f514db29fb5..7c703980de15 100644 --- a/docs/docs/target/container_image.md +++ b/docs/docs/target/container_image.md @@ -297,7 +297,7 @@ Trivy supports registries that comply with the following specifications. - [Docker Registry HTTP API V2](https://docs.docker.com/registry/spec/api/) - [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec) -You can configure credentials with `trivy auth login`. +You can configure credentials with `trivy registry login`. See [here](../advanced/private-registries/index.md) for the detail. ### Tar Files diff --git a/integration/registry_test.go b/integration/registry_test.go index ce77db5ad74a..aded09adce35 100644 --- a/integration/registry_test.go +++ b/integration/registry_test.go @@ -184,7 +184,7 @@ func TestRegistry(t *testing.T) { golden: "testdata/alpine-310.json.golden", }, { - name: "authenticate with 'trivy auth login'", + name: "authenticate with 'trivy registry login'", imageName: "alpine:3.10", imageFile: "testdata/fixtures/images/alpine-310.tar.gz", os: "alpine 3.10.2", @@ -295,7 +295,7 @@ func setupEnv(t *testing.T, imageRef name.Reference, baseDir string, opt registr case opt.AuthLogin: t.Setenv("DOCKER_CONFIG", t.TempDir()) err := execute([]string{ - "auth", + "registry", "login", "--username", opt.Username, diff --git a/mkdocs.yml b/mkdocs.yml index 1d3d6276e2c3..00e458e15a91 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -158,10 +158,6 @@ nav: - Configuration: - CLI: - Overview: docs/references/configuration/cli/trivy.md - - Auth: - - Auth: docs/references/configuration/cli/trivy_auth.md - - Auth Login: docs/references/configuration/cli/trivy_auth_login.md - - Auth Logout: docs/references/configuration/cli/trivy_auth_logout.md - Clean: docs/references/configuration/cli/trivy_clean.md - Config: docs/references/configuration/cli/trivy_config.md - Convert: docs/references/configuration/cli/trivy_convert.md @@ -182,6 +178,10 @@ nav: - Plugin Update: docs/references/configuration/cli/trivy_plugin_update.md - Plugin Upgrade: docs/references/configuration/cli/trivy_plugin_upgrade.md - Plugin Search: docs/references/configuration/cli/trivy_plugin_search.md + - Registry: + - Registry: docs/references/configuration/cli/trivy_registry.md + - Registry Login: docs/references/configuration/cli/trivy_registry_login.md + - Registry Logout: docs/references/configuration/cli/trivy_registry_logout.md - Repository: docs/references/configuration/cli/trivy_repository.md - Rootfs: docs/references/configuration/cli/trivy_rootfs.md - SBOM: docs/references/configuration/cli/trivy_sbom.md diff --git a/pkg/commands/app.go b/pkg/commands/app.go index eec063a3eba3..dbe3d54ba373 100644 --- a/pkg/commands/app.go +++ b/pkg/commands/app.go @@ -100,7 +100,7 @@ func NewApp() *cobra.Command { NewVersionCommand(globalFlags), NewVMCommand(globalFlags), NewCleanCommand(globalFlags), - NewAuthCommand(globalFlags), + NewRegistryCommand(globalFlags), NewVEXCommand(globalFlags), ) @@ -1235,11 +1235,11 @@ func NewCleanCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { return cmd } -func NewAuthCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { +func NewRegistryCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { cmd := &cobra.Command{ - Use: "auth [flags]", + Use: "registry [flags]", GroupID: groupUtility, - Short: "Authentication", + Short: "Manage registry authentication", SilenceErrors: true, SilenceUsage: true, } @@ -1255,7 +1255,7 @@ func NewAuthCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { SilenceErrors: true, SilenceUsage: true, Example: ` # Log in to reg.example.com - cat ~/my_password.txt | trivy auth login --username foo --password-stdin reg.example.com`, + cat ~/my_password.txt | trivy registry login --username foo --password-stdin reg.example.com`, Args: cobra.ExactArgs(1), PreRunE: func(cmd *cobra.Command, args []string) error { if err := loginFlags.Bind(cmd); err != nil { @@ -1277,7 +1277,7 @@ func NewAuthCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { SilenceErrors: true, SilenceUsage: true, Example: ` # Log out of reg.example.com - trivy auth logout reg.example.com`, + trivy registry logout reg.example.com`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { return auth.Logout(cmd.Context(), args[0]) From ad914123c4d203af1e1da6b7e2d3e49d9d3831d8 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Wed, 16 Oct 2024 10:15:17 +0600 Subject: [PATCH 47/94] feat(misconf): public network support for Azure Storage Account (#7601) Signed-off-by: nikpivkin --- pkg/iac/adapters/arm/storage/adapt.go | 6 +++++ pkg/iac/adapters/arm/storage/adapt_test.go | 27 ++++++++++--------- .../adapters/terraform/azure/storage/adapt.go | 3 ++- .../terraform/azure/storage/adapt_test.go | 22 ++++++++++++--- pkg/iac/providers/azure/storage/storage.go | 15 ++++++----- pkg/iac/rego/schemas/cloud.json | 4 +++ 6 files changed, 54 insertions(+), 23 deletions(-) diff --git a/pkg/iac/adapters/arm/storage/adapt.go b/pkg/iac/adapters/arm/storage/adapt.go index 018949e24e10..186ab5beda9d 100644 --- a/pkg/iac/adapters/arm/storage/adapt.go +++ b/pkg/iac/adapters/arm/storage/adapt.go @@ -62,6 +62,12 @@ func adaptAccounts(deployment azure.Deployment) []storage.Account { MinimumTLSVersion: resource.Properties.GetMapValue("minimumTlsVersion").AsStringValue("", resource.Properties.GetMetadata()), Queues: queues, } + + publicNetworkAccess := resource.Properties.GetMapValue("publicNetworkAccess") + account.PublicNetworkAccess = types.Bool( + publicNetworkAccess.AsStringValue("Enabled", publicNetworkAccess.Metadata).EqualTo("Enabled"), + publicNetworkAccess.Metadata, + ) accounts = append(accounts, account) } return accounts diff --git a/pkg/iac/adapters/arm/storage/adapt_test.go b/pkg/iac/adapters/arm/storage/adapt_test.go index f4fd81f47ad2..a6965ca1560c 100644 --- a/pkg/iac/adapters/arm/storage/adapt_test.go +++ b/pkg/iac/adapters/arm/storage/adapt_test.go @@ -6,17 +6,17 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - azure2 "github.com/aquasecurity/trivy/pkg/iac/scanners/azure" + "github.com/aquasecurity/trivy/pkg/iac/scanners/azure" "github.com/aquasecurity/trivy/pkg/iac/types" ) func Test_AdaptStorageDefaults(t *testing.T) { - input := azure2.Deployment{ - Resources: []azure2.Resource{ + input := azure.Deployment{ + Resources: []azure.Resource{ { - Type: azure2.NewValue("Microsoft.Storage/storageAccounts", types.NewTestMetadata()), - Properties: azure2.NewValue(make(map[string]azure2.Value), types.NewTestMetadata()), + Type: azure.NewValue("Microsoft.Storage/storageAccounts", types.NewTestMetadata()), + Properties: azure.NewValue(make(map[string]azure.Value), types.NewTestMetadata()), }, }, } @@ -28,19 +28,21 @@ func Test_AdaptStorageDefaults(t *testing.T) { account := output.Accounts[0] assert.Equal(t, "", account.MinimumTLSVersion.Value()) assert.False(t, account.EnforceHTTPS.Value()) + assert.True(t, account.PublicNetworkAccess.Value()) } func Test_AdaptStorage(t *testing.T) { - input := azure2.Deployment{ - Resources: []azure2.Resource{ + input := azure.Deployment{ + Resources: []azure.Resource{ { - Type: azure2.NewValue("Microsoft.Storage/storageAccounts", types.NewTestMetadata()), - Name: azure2.Value{}, - Properties: azure2.NewValue(map[string]azure2.Value{ - "minimumTlsVersion": azure2.NewValue("TLS1_2", types.NewTestMetadata()), - "supportsHttpsTrafficOnly": azure2.NewValue(true, types.NewTestMetadata()), + Type: azure.NewValue("Microsoft.Storage/storageAccounts", types.NewTestMetadata()), + Name: azure.Value{}, + Properties: azure.NewValue(map[string]azure.Value{ + "minimumTlsVersion": azure.NewValue("TLS1_2", types.NewTestMetadata()), + "supportsHttpsTrafficOnly": azure.NewValue(true, types.NewTestMetadata()), + "publicNetworkAccess": azure.NewValue("Disabled", types.NewTestMetadata()), }, types.NewTestMetadata()), }, }, @@ -53,5 +55,6 @@ func Test_AdaptStorage(t *testing.T) { account := output.Accounts[0] assert.Equal(t, "TLS1_2", account.MinimumTLSVersion.Value()) assert.True(t, account.EnforceHTTPS.Value()) + assert.False(t, account.PublicNetworkAccess.Value()) } diff --git a/pkg/iac/adapters/terraform/azure/storage/adapt.go b/pkg/iac/adapters/terraform/azure/storage/adapt.go index 6a51cf1fca2b..3f125c3c828f 100644 --- a/pkg/iac/adapters/terraform/azure/storage/adapt.go +++ b/pkg/iac/adapters/terraform/azure/storage/adapt.go @@ -108,7 +108,8 @@ func adaptAccount(resource *terraform.Block) storage.Account { Metadata: resource.GetMetadata(), EnableLogging: iacTypes.BoolDefault(false, resource.GetMetadata()), }, - MinimumTLSVersion: iacTypes.StringDefault(minimumTlsVersionOneTwo, resource.GetMetadata()), + MinimumTLSVersion: iacTypes.StringDefault(minimumTlsVersionOneTwo, resource.GetMetadata()), + PublicNetworkAccess: resource.GetAttribute("public_network_access_enabled").AsBoolValueOrDefault(true, resource), } networkRulesBlocks := resource.GetBlocks("network_rules") diff --git a/pkg/iac/adapters/terraform/azure/storage/adapt_test.go b/pkg/iac/adapters/terraform/azure/storage/adapt_test.go index 87ffb1a919f4..5f576731d432 100644 --- a/pkg/iac/adapters/terraform/azure/storage/adapt_test.go +++ b/pkg/iac/adapters/terraform/azure/storage/adapt_test.go @@ -18,6 +18,20 @@ func Test_Adapt(t *testing.T) { terraform string expected storage.Storage }{ + { + name: "default", + terraform: `resource "azurerm_storage_account" "example" {}`, + expected: storage.Storage{ + Accounts: []storage.Account{ + { + PublicNetworkAccess: iacTypes.BoolTest(true), + MinimumTLSVersion: iacTypes.StringTest(minimumTlsVersionOneTwo), + EnforceHTTPS: iacTypes.BoolTest(true), + }, + {}, + }, + }, + }, { name: "defined", terraform: ` @@ -45,6 +59,7 @@ func Test_Adapt(t *testing.T) { } } min_tls_version = "TLS1_2" + public_network_access_enabled = false } resource "azurerm_storage_account_network_rules" "test" { @@ -65,9 +80,10 @@ func Test_Adapt(t *testing.T) { Accounts: []storage.Account{ { - Metadata: iacTypes.NewTestMetadata(), - EnforceHTTPS: iacTypes.Bool(true, iacTypes.NewTestMetadata()), - MinimumTLSVersion: iacTypes.String("TLS1_2", iacTypes.NewTestMetadata()), + Metadata: iacTypes.NewTestMetadata(), + EnforceHTTPS: iacTypes.Bool(true, iacTypes.NewTestMetadata()), + MinimumTLSVersion: iacTypes.String("TLS1_2", iacTypes.NewTestMetadata()), + PublicNetworkAccess: iacTypes.BoolTest(false), NetworkRules: []storage.NetworkRule{ { Metadata: iacTypes.NewTestMetadata(), diff --git a/pkg/iac/providers/azure/storage/storage.go b/pkg/iac/providers/azure/storage/storage.go index cccc5d55eda1..ce86ec8698cc 100755 --- a/pkg/iac/providers/azure/storage/storage.go +++ b/pkg/iac/providers/azure/storage/storage.go @@ -9,13 +9,14 @@ type Storage struct { } type Account struct { - Metadata iacTypes.Metadata - NetworkRules []NetworkRule - EnforceHTTPS iacTypes.BoolValue - Containers []Container - QueueProperties QueueProperties - MinimumTLSVersion iacTypes.StringValue - Queues []Queue + Metadata iacTypes.Metadata + NetworkRules []NetworkRule + EnforceHTTPS iacTypes.BoolValue + Containers []Container + QueueProperties QueueProperties + MinimumTLSVersion iacTypes.StringValue + Queues []Queue + PublicNetworkAccess iacTypes.BoolValue } type Queue struct { diff --git a/pkg/iac/rego/schemas/cloud.json b/pkg/iac/rego/schemas/cloud.json index b034f24fa104..d0ce7ffe515a 100644 --- a/pkg/iac/rego/schemas/cloud.json +++ b/pkg/iac/rego/schemas/cloud.json @@ -5396,6 +5396,10 @@ "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.providers.azure.storage.NetworkRule" } }, + "publicnetworkaccess": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.BoolValue" + }, "queueproperties": { "type": "object", "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.providers.azure.storage.QueueProperties" From 83e5b83acc20861b28f72a0796fc46a7325898f6 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Wed, 16 Oct 2024 10:31:20 +0600 Subject: [PATCH 48/94] docs: add note about disabled DS016 check (#7724) Signed-off-by: nikpivkin --- docs/docs/target/container_image.md | 2 ++ .../analyzer/imgconf/dockerfile/dockerfile.go | 9 ++++--- pkg/misconf/scanner.go | 25 ++++++++++++++----- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/docs/docs/target/container_image.md b/docs/docs/target/container_image.md index 7c703980de15..f1c491071a3f 100644 --- a/docs/docs/target/container_image.md +++ b/docs/docs/target/container_image.md @@ -154,6 +154,8 @@ See https://avd.aquasec.com/misconfig/ds026 !!! tip You can see how each layer is created with `docker history`. +The [AVD-DS-0016](https://avd.aquasec.com/misconfig/dockerfile/general/avd-ds-0016/) check is disabled for this scan type, see [issue](https://github.com/aquasecurity/trivy/issues/7368) for details. + ### Secrets Trivy detects secrets on the configuration of container images. The image config is converted into JSON and Trivy scans the file for secrets. diff --git a/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go b/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go index c79a81f54c61..35a4fc12fea1 100644 --- a/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go +++ b/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go @@ -16,8 +16,11 @@ import ( "github.com/aquasecurity/trivy/pkg/misconf" ) -var disabledChecks = []string{ - "DS016", // See https://github.com/aquasecurity/trivy/issues/7368 +var disabledChecks = []misconf.DisabledCheck{ + { + ID: "DS016", Scanner: string(analyzer.TypeHistoryDockerfile), + Reason: "See https://github.com/aquasecurity/trivy/issues/7368", + }, } const analyzerVersion = 1 @@ -31,7 +34,7 @@ type historyAnalyzer struct { } func newHistoryAnalyzer(opts analyzer.ConfigAnalyzerOptions) (analyzer.ConfigAnalyzer, error) { - opts.MisconfScannerOption.DisabledCheckIDs = append(opts.MisconfScannerOption.DisabledCheckIDs, disabledChecks...) + opts.MisconfScannerOption.DisabledChecks = append(opts.MisconfScannerOption.DisabledChecks, disabledChecks...) s, err := misconf.NewScanner(detection.FileTypeDockerfile, opts.MisconfScannerOption) if err != nil { return nil, xerrors.Errorf("misconfiguration scanner error: %w", err) diff --git a/pkg/misconf/scanner.go b/pkg/misconf/scanner.go index 04fc28bc5296..7a3642dfe895 100644 --- a/pkg/misconf/scanner.go +++ b/pkg/misconf/scanner.go @@ -50,6 +50,12 @@ var enablediacTypes = map[detection.FileType]types.ConfigType{ detection.FileTypeYAML: types.YAML, } +type DisabledCheck struct { + ID string + Scanner string // For logging + Reason string // For logging +} + type ScannerOption struct { Trace bool RegoOnly bool @@ -74,9 +80,9 @@ type ScannerOption struct { FilePatterns []string ConfigFileSchemas []*ConfigFileSchema - DisabledCheckIDs []string - SkipFiles []string - SkipDirs []string + DisabledChecks []DisabledCheck + SkipFiles []string + SkipDirs []string } func (o *ScannerOption) Sort() { @@ -133,6 +139,7 @@ func NewScanner(t detection.FileType, opt ScannerOption) (*Scanner, error) { } func (s *Scanner) Scan(ctx context.Context, fsys fs.FS) ([]types.Misconfiguration, error) { + ctx = log.WithContextPrefix(ctx, log.PrefixMisconfiguration) newfs, err := s.filterFS(fsys) if err != nil { return nil, xerrors.Errorf("fs filter error: %w", err) @@ -141,12 +148,12 @@ func (s *Scanner) Scan(ctx context.Context, fsys fs.FS) ([]types.Misconfiguratio return nil, nil } - log.Debug("Scanning files for misconfigurations...", log.String("scanner", s.scanner.Name())) + log.DebugContext(ctx, "Scanning files for misconfigurations...", log.String("scanner", s.scanner.Name())) results, err := s.scanner.ScanFS(ctx, newfs, ".") if err != nil { var invalidContentError *cfparser.InvalidContentError if errors.As(err, &invalidContentError) { - log.Error("scan was broken with InvalidContentError", s.scanner.Name(), log.Err(err)) + log.ErrorContext(ctx, "scan was broken with InvalidContentError", s.scanner.Name(), log.Err(err)) return nil, nil } return nil, xerrors.Errorf("scan config error: %w", err) @@ -211,11 +218,17 @@ func (s *Scanner) filterFS(fsys fs.FS) (fs.FS, error) { } func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerOption, error) { + disabledCheckIDs := lo.Map(opt.DisabledChecks, func(check DisabledCheck, _ int) string { + log.Info("Check disabled", log.Prefix(log.PrefixMisconfiguration), log.String("ID", check.ID), + log.String("scanner", check.Scanner), log.String("reason", check.Reason)) + return check.ID + }) + opts := []options.ScannerOption{ rego.WithEmbeddedPolicies(!opt.DisableEmbeddedPolicies), rego.WithEmbeddedLibraries(!opt.DisableEmbeddedLibraries), options.ScannerWithIncludeDeprecatedChecks(opt.IncludeDeprecatedChecks), - rego.WithDisabledCheckIDs(opt.DisabledCheckIDs...), + rego.WithDisabledCheckIDs(disabledCheckIDs...), } policyFS, policyPaths, err := CreatePolicyFS(opt.PolicyPaths) From bcfc37bb16c6ddb3faa439cac0cec036475f4d30 Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Thu, 17 Oct 2024 03:41:59 +0400 Subject: [PATCH 49/94] test: define constants for test images (#7739) Signed-off-by: knqyf263 Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> --- .github/workflows/cache-test-images.yaml | 6 +- .github/workflows/test.yaml | 9 ++- integration/testimages.ini | 3 + internal/testutil/image.go | 67 +++++++++++++++++++ magefiles/fixture.go | 10 +-- pkg/attestation/attestation_test.go | 3 +- .../analyzer/language/java/jar/jar_test.go | 4 -- pkg/fanal/test/integration/containerd_test.go | 23 ++++--- pkg/fanal/test/integration/registry_test.go | 9 +-- 9 files changed, 104 insertions(+), 30 deletions(-) create mode 100644 integration/testimages.ini create mode 100644 internal/testutil/image.go diff --git a/.github/workflows/cache-test-images.yaml b/.github/workflows/cache-test-images.yaml index a03dc683e3ae..4b73cc2fb5bc 100644 --- a/.github/workflows/cache-test-images.yaml +++ b/.github/workflows/cache-test-images.yaml @@ -27,7 +27,8 @@ jobs: if: github.ref_name == 'main' id: image-digest run: | - IMAGE_LIST=$(skopeo list-tags docker://ghcr.io/aquasecurity/trivy-test-images) + source integration/testimages.ini + IMAGE_LIST=$(skopeo list-tags docker://$TEST_IMAGES) DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) echo "digest=$DIGEST" >> $GITHUB_OUTPUT @@ -67,7 +68,8 @@ jobs: if: github.ref_name == 'main' id: image-digest run: | - IMAGE_LIST=$(skopeo list-tags docker://ghcr.io/aquasecurity/trivy-test-vm-images) + source integration/testimages.ini + IMAGE_LIST=$(skopeo list-tags docker://$TEST_VM_IMAGES) DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) echo "digest=$DIGEST" >> $GITHUB_OUTPUT diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 74b0933c6ef6..8932a683c5bc 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -90,7 +90,8 @@ jobs: - name: Generate image list digest id: image-digest run: | - IMAGE_LIST=$(skopeo list-tags docker://ghcr.io/aquasecurity/trivy-test-images) + source integration/testimages.ini + IMAGE_LIST=$(skopeo list-tags docker://$TEST_IMAGES) DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) echo "digest=$DIGEST" >> $GITHUB_OUTPUT @@ -147,7 +148,8 @@ jobs: - name: Generate image list digest id: image-digest run: | - IMAGE_LIST=$(skopeo list-tags docker://ghcr.io/aquasecurity/trivy-test-images) + source integration/testimages.ini + IMAGE_LIST=$(skopeo list-tags docker://$TEST_IMAGES) DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) echo "digest=$DIGEST" >> $GITHUB_OUTPUT @@ -185,7 +187,8 @@ jobs: - name: Generate image list digest id: image-digest run: | - IMAGE_LIST=$(skopeo list-tags docker://ghcr.io/aquasecurity/trivy-test-vm-images) + source integration/testimages.ini + IMAGE_LIST=$(skopeo list-tags docker://$TEST_VM_IMAGES) DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) echo "digest=$DIGEST" >> $GITHUB_OUTPUT diff --git a/integration/testimages.ini b/integration/testimages.ini new file mode 100644 index 000000000000..1a7b8ef1a0c0 --- /dev/null +++ b/integration/testimages.ini @@ -0,0 +1,3 @@ +# Configuration file for both shell scripts and Go programs +TEST_IMAGES=ghcr.io/aquasecurity/trivy-test-images +TEST_VM_IMAGES=ghcr.io/aquasecurity/trivy-test-vm-images diff --git a/internal/testutil/image.go b/internal/testutil/image.go new file mode 100644 index 000000000000..dba54bc23dff --- /dev/null +++ b/internal/testutil/image.go @@ -0,0 +1,67 @@ +package testutil + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "runtime" + "strings" +) + +var ( + testImages string + testVMImages string +) + +func init() { + _, b, _, _ := runtime.Caller(0) + currentDir := filepath.Dir(b) + f, err := os.Open(filepath.Join(currentDir, "..", "..", "integration", "testimages.ini")) + if err != nil { + panic(err) + } + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + if strings.HasPrefix(scanner.Text(), "#") { + continue + } + parts := strings.SplitN(scanner.Text(), "=", 2) + if len(parts) == 2 { + key := strings.TrimSpace(parts[0]) + value := strings.TrimSpace(parts[1]) + switch key { + case "TEST_IMAGES": + testImages = value + case "TEST_VM_IMAGES": + testVMImages = value + } + } + } + if err = scanner.Err(); err != nil { + panic(err) + } +} + +func ImageName(subpath, tag, digest string) string { + return imageName(testImages, subpath, tag, digest) +} + +func VMImageName(subpath, tag, digest string) string { + return imageName(testVMImages, subpath, tag, digest) +} + +func imageName(img, subpath, tag, digest string) string { + if subpath != "" { + img = fmt.Sprintf("%s/%s", img, subpath) + } + if tag != "" { + img = fmt.Sprintf("%s:%s", img, tag) + } + if digest != "" { + img = fmt.Sprintf("%s@%s", img, digest) + } + return img +} diff --git a/magefiles/fixture.go b/magefiles/fixture.go index 0ed9ae8d4217..0112a8421133 100644 --- a/magefiles/fixture.go +++ b/magefiles/fixture.go @@ -10,13 +10,13 @@ import ( "github.com/google/go-containerregistry/pkg/crane" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/magefile/mage/sh" + + "github.com/aquasecurity/trivy/internal/testutil" ) func fixtureContainerImages() error { - const ( - testImages = "ghcr.io/aquasecurity/trivy-test-images" - dir = "integration/testdata/fixtures/images/" - ) + var testImages = testutil.ImageName("", "", "") + const dir = "integration/testdata/fixtures/images/" if err := os.MkdirAll(dir, 0750); err != nil { return err } @@ -48,8 +48,8 @@ func fixtureContainerImages() error { } func fixtureVMImages() error { + var testVMImages = testutil.VMImageName("", "", "") const ( - testVMImages = "ghcr.io/aquasecurity/trivy-test-vm-images" titleAnnotation = "org.opencontainers.image.title" dir = "integration/testdata/fixtures/vm-images/" ) diff --git a/pkg/attestation/attestation_test.go b/pkg/attestation/attestation_test.go index 763878f4ae41..de75b5676692 100644 --- a/pkg/attestation/attestation_test.go +++ b/pkg/attestation/attestation_test.go @@ -9,6 +9,7 @@ import ( slsa "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/attestation" ) @@ -27,7 +28,7 @@ func TestStatement_UnmarshalJSON(t *testing.T) { PredicateType: "cosign.sigstore.dev/attestation/v1", Subject: []in_toto.Subject{ { - Name: "ghcr.io/aquasecurity/trivy-test-images", + Name: testutil.ImageName("", "", ""), Digest: slsa.DigestSet{ "sha256": "72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb", }, diff --git a/pkg/fanal/analyzer/language/java/jar/jar_test.go b/pkg/fanal/analyzer/language/java/jar/jar_test.go index 146b60c1bbd6..58e7221066ac 100644 --- a/pkg/fanal/analyzer/language/java/jar/jar_test.go +++ b/pkg/fanal/analyzer/language/java/jar/jar_test.go @@ -18,10 +18,6 @@ import ( _ "modernc.org/sqlite" ) -const ( - defaultJavaDBRepository = "ghcr.io/aquasecurity/trivy-java-db" -) - func Test_javaLibraryAnalyzer_Analyze(t *testing.T) { tests := []struct { name string diff --git a/pkg/fanal/test/integration/containerd_test.go b/pkg/fanal/test/integration/containerd_test.go index d16ad3dac059..568af60528ea 100644 --- a/pkg/fanal/test/integration/containerd_test.go +++ b/pkg/fanal/test/integration/containerd_test.go @@ -27,6 +27,7 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" + "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/applier" @@ -77,7 +78,7 @@ func startContainerd(t *testing.T, ctx context.Context, hostPath string) { t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true") req := testcontainers.ContainerRequest{ Name: "containerd", - Image: "ghcr.io/aquasecurity/trivy-test-images/containerd:latest", + Image: testutil.ImageName("containerd", "latest", ""), Entrypoint: []string{ "/bin/sh", "-c", @@ -122,7 +123,7 @@ func TestContainerd_SearchLocalStoreByNameOrDigest(t *testing.T) { digest := "sha256:f12582b2f2190f350e3904462c1c23aaf366b4f76705e97b199f9bbded1d816a" basename := "hello" tag := "world" - importedImageOriginalName := "ghcr.io/aquasecurity/trivy-test-images:alpine-310" + importedImageOriginalName := testutil.ImageName("", "alpine-310", "") tests := []struct { name string @@ -299,15 +300,15 @@ func localImageTestWithNamespace(t *testing.T, namespace string) { }{ { name: "alpine 3.10", - imageName: "ghcr.io/aquasecurity/trivy-test-images:alpine-310", + imageName: testutil.ImageName("", "alpine-310", ""), tarArchive: "../../../../integration/testdata/fixtures/images/alpine-310.tar.gz", wantMetadata: artifact.ImageMetadata{ ID: "sha256:961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4", DiffIDs: []string{ "sha256:03901b4a2ea88eeaad62dbe59b072b28b6efa00491962b8741081c5df50c65e0", }, - RepoTags: []string{"ghcr.io/aquasecurity/trivy-test-images:alpine-310"}, - RepoDigests: []string{"ghcr.io/aquasecurity/trivy-test-images@sha256:f12582b2f2190f350e3904462c1c23aaf366b4f76705e97b199f9bbded1d816a"}, + RepoTags: []string{testutil.ImageName("", "alpine-310", "")}, + RepoDigests: []string{testutil.ImageName("", "", "sha256:f12582b2f2190f350e3904462c1c23aaf366b4f76705e97b199f9bbded1d816a")}, ConfigFile: v1.ConfigFile{ Architecture: "amd64", Created: v1.Time{ @@ -347,7 +348,7 @@ func localImageTestWithNamespace(t *testing.T, namespace string) { }, { name: "vulnimage", - imageName: "ghcr.io/aquasecurity/trivy-test-images:vulnimage", + imageName: testutil.ImageName("", "vulnimage", ""), tarArchive: "../../../../integration/testdata/fixtures/images/vulnimage.tar.gz", wantMetadata: artifact.ImageMetadata{ ID: "sha256:c17083664da903e13e9092fa3a3a1aeee2431aa2728298e3dbcec72f26369c41", @@ -373,8 +374,8 @@ func localImageTestWithNamespace(t *testing.T, namespace string) { "sha256:ba17950e91742d6ac7055ea3a053fe764486658ca1ce8188f1e427b1fe2bc4da", "sha256:6ef42db7800507577383edf1937cb203b9b85f619feed6046594208748ceb52c", }, - RepoTags: []string{"ghcr.io/aquasecurity/trivy-test-images:vulnimage"}, - RepoDigests: []string{"ghcr.io/aquasecurity/trivy-test-images@sha256:e74abbfd81e00baaf464cf9e09f8b24926e5255171e3150a60aa341ce064688f"}, + RepoTags: []string{testutil.ImageName("", "vulnimage", "")}, + RepoDigests: []string{testutil.ImageName("", "", "sha256:e74abbfd81e00baaf464cf9e09f8b24926e5255171e3150a60aa341ce064688f")}, ConfigFile: v1.ConfigFile{ Architecture: "amd64", Created: v1.Time{ @@ -750,14 +751,14 @@ func TestContainerd_PullImage(t *testing.T) { }{ { name: "remote alpine 3.10", - imageName: "ghcr.io/aquasecurity/trivy-test-images:alpine-310", + imageName: testutil.ImageName("", "alpine-310", ""), wantMetadata: artifact.ImageMetadata{ ID: "sha256:961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4", DiffIDs: []string{ "sha256:03901b4a2ea88eeaad62dbe59b072b28b6efa00491962b8741081c5df50c65e0", }, - RepoTags: []string{"ghcr.io/aquasecurity/trivy-test-images:alpine-310"}, - RepoDigests: []string{"ghcr.io/aquasecurity/trivy-test-images@sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb"}, + RepoTags: []string{testutil.ImageName("", "alpine-310", "")}, + RepoDigests: []string{testutil.ImageName("", "", "sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb")}, ConfigFile: v1.ConfigFile{ Architecture: "amd64", Created: v1.Time{ diff --git a/pkg/fanal/test/integration/registry_test.go b/pkg/fanal/test/integration/registry_test.go index 5b062e425729..4bca93f0ccba 100644 --- a/pkg/fanal/test/integration/registry_test.go +++ b/pkg/fanal/test/integration/registry_test.go @@ -20,6 +20,7 @@ import ( testcontainers "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" + "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/all" @@ -95,7 +96,7 @@ func TestTLSRegistry(t *testing.T) { }{ { name: "happy path", - imageName: "ghcr.io/aquasecurity/trivy-test-images:alpine-310", + imageName: testutil.ImageName("", "alpine-310", ""), imageFile: "../../../../integration/testdata/fixtures/images/alpine-310.tar.gz", option: types.ImageOptions{ RegistryOptions: types.RegistryOptions{ @@ -120,7 +121,7 @@ func TestTLSRegistry(t *testing.T) { }, { name: "happy path with docker login", - imageName: "ghcr.io/aquasecurity/trivy-test-images:alpine-310", + imageName: testutil.ImageName("", "alpine-310", ""), imageFile: "../../../../integration/testdata/fixtures/images/alpine-310.tar.gz", option: types.ImageOptions{ RegistryOptions: types.RegistryOptions{ @@ -140,7 +141,7 @@ func TestTLSRegistry(t *testing.T) { }, { name: "sad path: tls verify", - imageName: "ghcr.io/aquasecurity/trivy-test-images:alpine-310", + imageName: testutil.ImageName("", "alpine-310", ""), imageFile: "../../../../integration/testdata/fixtures/images/alpine-310.tar.gz", option: types.ImageOptions{ RegistryOptions: types.RegistryOptions{ @@ -156,7 +157,7 @@ func TestTLSRegistry(t *testing.T) { }, { name: "sad path: no credential", - imageName: "ghcr.io/aquasecurity/trivy-test-images:alpine-310", + imageName: testutil.ImageName("", "alpine-310", ""), imageFile: "../../../../integration/testdata/fixtures/images/alpine-310.tar.gz", option: types.ImageOptions{ RegistryOptions: types.RegistryOptions{ From 2eaa17e0717940b27a79050e2efd9213b71178c9 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Thu, 17 Oct 2024 08:29:39 +0600 Subject: [PATCH 50/94] feat(misconf): ssl_mode support for GCP SQL DB instance (#7564) Signed-off-by: nikpivkin --- pkg/iac/adapters/terraform/google/sql/adapt.go | 12 ++++-------- pkg/iac/adapters/terraform/google/sql/adapt_test.go | 2 ++ pkg/iac/providers/google/sql/sql.go | 1 + pkg/iac/rego/schemas/cloud.json | 4 ++++ 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pkg/iac/adapters/terraform/google/sql/adapt.go b/pkg/iac/adapters/terraform/google/sql/adapt.go index 6418942384d4..6d68795bcfac 100644 --- a/pkg/iac/adapters/terraform/google/sql/adapt.go +++ b/pkg/iac/adapters/terraform/google/sql/adapt.go @@ -52,6 +52,7 @@ func adaptInstance(resource *terraform.Block) sql.DatabaseInstance { IPConfiguration: sql.IPConfiguration{ Metadata: resource.GetMetadata(), RequireTLS: iacTypes.BoolDefault(false, resource.GetMetadata()), + SSLMode: iacTypes.String("", resource.GetMetadata()), EnableIPv4: iacTypes.BoolDefault(true, resource.GetMetadata()), AuthorizedNetworks: nil, }, @@ -125,12 +126,6 @@ func adaptIPConfig(resource *terraform.Block) sql.IPConfiguration { CIDR iacTypes.StringValue } - tlsRequiredAttr := resource.GetAttribute("require_ssl") - tlsRequiredVal := tlsRequiredAttr.AsBoolValueOrDefault(false, resource) - - ipv4enabledAttr := resource.GetAttribute("ipv4_enabled") - ipv4enabledVal := ipv4enabledAttr.AsBoolValueOrDefault(true, resource) - authNetworksBlocks := resource.GetBlocks("authorized_networks") for _, authBlock := range authNetworksBlocks { nameVal := authBlock.GetAttribute("name").AsStringValueOrDefault("", authBlock) @@ -147,8 +142,9 @@ func adaptIPConfig(resource *terraform.Block) sql.IPConfiguration { return sql.IPConfiguration{ Metadata: resource.GetMetadata(), - RequireTLS: tlsRequiredVal, - EnableIPv4: ipv4enabledVal, + RequireTLS: resource.GetAttribute("require_ssl").AsBoolValueOrDefault(false, resource), + SSLMode: resource.GetAttribute("ssl_mode").AsStringValueOrDefault("", resource), + EnableIPv4: resource.GetAttribute("ipv4_enabled").AsBoolValueOrDefault(true, resource), AuthorizedNetworks: authorizedNetworks, } } diff --git a/pkg/iac/adapters/terraform/google/sql/adapt_test.go b/pkg/iac/adapters/terraform/google/sql/adapt_test.go index 29e89d6282b7..fd3207ed3547 100644 --- a/pkg/iac/adapters/terraform/google/sql/adapt_test.go +++ b/pkg/iac/adapters/terraform/google/sql/adapt_test.go @@ -34,6 +34,7 @@ func Test_Adapt(t *testing.T) { name = "internal" } require_ssl = true + ssl_mode = "TRUSTED_CLIENT_CERTIFICATE_REQUIRED" } } } @@ -67,6 +68,7 @@ func Test_Adapt(t *testing.T) { Metadata: iacTypes.NewTestMetadata(), RequireTLS: iacTypes.Bool(true, iacTypes.NewTestMetadata()), EnableIPv4: iacTypes.Bool(false, iacTypes.NewTestMetadata()), + SSLMode: iacTypes.StringTest("TRUSTED_CLIENT_CERTIFICATE_REQUIRED"), AuthorizedNetworks: []struct { Name iacTypes.StringValue CIDR iacTypes.StringValue diff --git a/pkg/iac/providers/google/sql/sql.go b/pkg/iac/providers/google/sql/sql.go index 18778dd1daef..672e78a42fbd 100755 --- a/pkg/iac/providers/google/sql/sql.go +++ b/pkg/iac/providers/google/sql/sql.go @@ -66,6 +66,7 @@ type Backups struct { type IPConfiguration struct { Metadata iacTypes.Metadata RequireTLS iacTypes.BoolValue + SSLMode iacTypes.StringValue EnableIPv4 iacTypes.BoolValue AuthorizedNetworks []struct { Name iacTypes.StringValue diff --git a/pkg/iac/rego/schemas/cloud.json b/pkg/iac/rego/schemas/cloud.json index d0ce7ffe515a..3cc6301429be 100644 --- a/pkg/iac/rego/schemas/cloud.json +++ b/pkg/iac/rego/schemas/cloud.json @@ -6991,6 +6991,10 @@ "requiretls": { "type": "object", "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.BoolValue" + }, + "sslmode": { + "type": "object", + "$ref": "#/definitions/github.aaakk.us.kg.aquasecurity.trivy.pkg.iac.types.StringValue" } } }, From 9da84f54fadbe6ad0d73983952e945ed63b666f3 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Thu, 17 Oct 2024 09:39:58 +0600 Subject: [PATCH 51/94] fix(misconf): change default ACL of digitalocean_spaces_bucket to private (#7577) Signed-off-by: nikpivkin --- pkg/iac/adapters/terraform/digitalocean/spaces/adapt.go | 2 +- pkg/iac/adapters/terraform/digitalocean/spaces/adapt_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/iac/adapters/terraform/digitalocean/spaces/adapt.go b/pkg/iac/adapters/terraform/digitalocean/spaces/adapt.go index 46d1f25fa386..a1a1c792d647 100644 --- a/pkg/iac/adapters/terraform/digitalocean/spaces/adapt.go +++ b/pkg/iac/adapters/terraform/digitalocean/spaces/adapt.go @@ -24,7 +24,7 @@ func adaptBuckets(modules terraform.Modules) []spaces.Bucket { Metadata: block.GetMetadata(), Name: block.GetAttribute("name").AsStringValueOrDefault("", block), Objects: nil, - ACL: block.GetAttribute("acl").AsStringValueOrDefault("public-read", block), + ACL: block.GetAttribute("acl").AsStringValueOrDefault("private", block), ForceDestroy: block.GetAttribute("force_destroy").AsBoolValueOrDefault(false, block), Versioning: spaces.Versioning{ Metadata: block.GetMetadata(), diff --git a/pkg/iac/adapters/terraform/digitalocean/spaces/adapt_test.go b/pkg/iac/adapters/terraform/digitalocean/spaces/adapt_test.go index cf3fc84e4ff7..e87987a3f473 100644 --- a/pkg/iac/adapters/terraform/digitalocean/spaces/adapt_test.go +++ b/pkg/iac/adapters/terraform/digitalocean/spaces/adapt_test.go @@ -69,7 +69,7 @@ func Test_adaptBuckets(t *testing.T) { Metadata: iacTypes.NewTestMetadata(), Name: iacTypes.String("", iacTypes.NewTestMetadata()), Objects: nil, - ACL: iacTypes.String("public-read", iacTypes.NewTestMetadata()), + ACL: iacTypes.String("private", iacTypes.NewTestMetadata()), ForceDestroy: iacTypes.Bool(false, iacTypes.NewTestMetadata()), Versioning: spaces.Versioning{ Metadata: iacTypes.NewTestMetadata(), From c8c14d36245623019f29d258f813d2325f7490f7 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Thu, 17 Oct 2024 09:40:14 +0600 Subject: [PATCH 52/94] fix(misconf): check if property is not nil before conversion (#7578) Signed-off-by: nikpivkin --- .../cloudformation/aws/ec2/adapt_test.go | 28 +++++++++++++++++++ .../parser/property_conversion.go | 7 +++++ 2 files changed, 35 insertions(+) diff --git a/pkg/iac/adapters/cloudformation/aws/ec2/adapt_test.go b/pkg/iac/adapters/cloudformation/aws/ec2/adapt_test.go index b218b95a4e99..c56471aa2bad 100644 --- a/pkg/iac/adapters/cloudformation/aws/ec2/adapt_test.go +++ b/pkg/iac/adapters/cloudformation/aws/ec2/adapt_test.go @@ -338,6 +338,34 @@ Resources: }, }, }, + { + name: "empty", + source: `--- +AWSTemplateFormatVersion: 2010-09-09 +Description: Godd example of excessive ports +Resources: + NetworkACL: + Type: AWS::EC2::NetworkAcl + Rule: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: + Ref: NetworkACL`, + expected: ec2.EC2{ + NetworkACLs: []ec2.NetworkACL{ + { + Rules: []ec2.NetworkACLRule{ + { + Action: types.StringTest("allow"), + Type: types.StringTest("ingress"), + FromPort: types.IntTest(-1), + ToPort: types.IntTest(-1), + }, + }, + }, + }, + }, + }, } for _, tt := range tests { diff --git a/pkg/iac/scanners/cloudformation/parser/property_conversion.go b/pkg/iac/scanners/cloudformation/parser/property_conversion.go index 35847bb35c5b..d1ef23d396f2 100644 --- a/pkg/iac/scanners/cloudformation/parser/property_conversion.go +++ b/pkg/iac/scanners/cloudformation/parser/property_conversion.go @@ -10,6 +10,10 @@ import ( ) func (p *Property) IsConvertableTo(conversionType cftypes.CfType) bool { + if p.IsNil() { + return false + } + switch conversionType { case cftypes.Int: return p.isConvertableToInt() @@ -62,6 +66,9 @@ func (p *Property) isConvertableToInt() bool { } func (p *Property) ConvertTo(conversionType cftypes.CfType) *Property { + if p.IsNil() { + return nil + } if p.Type() == conversionType { return p From 778df828eaad9827cb833c6285058a33aa2b83ca Mon Sep 17 00:00:00 2001 From: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:54:12 +0600 Subject: [PATCH 53/94] fix(java): correctly inherit `version` and `scope` from upper/root `depManagement` and `dependencies` into parents (#7541) Signed-off-by: knqyf263 Co-authored-by: knqyf263 --- pkg/dependency/parser/java/pom/parse.go | 147 ++++---- pkg/dependency/parser/java/pom/parse_test.go | 344 ++++++++++++++++++ pkg/dependency/parser/java/pom/pom.go | 29 +- .../pom.xml | 29 ++ .../pom.xml | 64 ++++ .../parent/pom.xml | 77 ++++ .../pom.xml | 39 ++ .../example-nested-scope-compile-1.0.0.pom | 41 +++ .../1.0.0/parent/pom.xml | 21 ++ .../example-nested-scope-empty-1.0.0.pom | 40 ++ .../1.0.0/parent/pom.xml | 21 ++ .../example-nested-scope-runtime-1.0.0.pom | 41 +++ .../1.0.0/parent/pom.xml | 21 ++ .../2.0.0/example-scope-compile-2.0.0.pom | 23 ++ .../2.0.0/example-scope-empty-2.0.0.pom | 22 ++ .../2.0.0/example-scope-runtime-2.0.0.pom | 23 ++ .../testdata/transitive-parents/base/pom.xml | 2 +- .../parent/pom.xml | 34 ++ .../pom.xml | 45 +++ .../top-parent/pom.xml | 34 ++ 20 files changed, 1013 insertions(+), 84 deletions(-) create mode 100644 pkg/dependency/parser/java/pom/testdata/inherit-scopes-from-child-deps-and-their-parents/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-children-from-root/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/parent/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/example-nested-scope-compile-1.0.0.pom create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/parent/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/example-nested-scope-empty-1.0.0.pom create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/parent/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/example-nested-scope-runtime-1.0.0.pom create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/parent/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-compile/2.0.0/example-scope-compile-2.0.0.pom create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-empty/2.0.0/example-scope-empty-2.0.0.pom create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-runtime/2.0.0/example-scope-runtime-2.0.0.pom create mode 100644 pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/top-parent/pom.xml diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go index 542abcac3c8a..2c8a194ea50b 100644 --- a/pkg/dependency/parser/java/pom/parse.go +++ b/pkg/dependency/parser/java/pom/parse.go @@ -96,7 +96,7 @@ func NewParser(filePath string, opts ...option) *Parser { } func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) { - content, err := parsePom(r) + content, err := parsePom(r, true) if err != nil { return nil, nil, xerrors.Errorf("failed to parse POM: %w", err) } @@ -107,7 +107,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc } // Analyze root POM - result, err := p.analyze(root, analysisOptions{lineNumber: true}) + result, err := p.analyze(root, analysisOptions{}) if err != nil { return nil, nil, xerrors.Errorf("analyze error (%s): %w", p.rootPath, err) } @@ -330,53 +330,27 @@ type analysisResult struct { type analysisOptions struct { exclusions map[string]struct{} depManagement []pomDependency // from the root POM - lineNumber bool // Save line numbers } func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) { - if pom == nil || pom.content == nil { + if pom.nil() { return analysisResult{}, nil } - // Update remoteRepositories pomReleaseRemoteRepos, pomSnapshotRemoteRepos := pom.repositories(p.servers) p.releaseRemoteRepos = lo.Uniq(append(pomReleaseRemoteRepos, p.releaseRemoteRepos...)) p.snapshotRemoteRepos = lo.Uniq(append(pomSnapshotRemoteRepos, p.snapshotRemoteRepos...)) - // We need to forward dependencyManagements from current and root pom to Parent, - // to use them for dependencies in parent. - // For better understanding see the following tests: - // - `dependency from parent uses version from child pom depManagement` - // - `dependency from parent uses version from root pom depManagement` - // - // depManagements from root pom has higher priority than depManagements from current pom. - depManagementForParent := lo.UniqBy(append(opts.depManagement, pom.content.DependencyManagement.Dependencies.Dependency...), - func(dep pomDependency) string { - return dep.Name() - }) - - // Parent - parent, err := p.parseParent(pom.filePath, pom.content.Parent, depManagementForParent) - if err != nil { - return analysisResult{}, xerrors.Errorf("parent error: %w", err) + // Resolve parent POM + if err := p.resolveParent(pom); err != nil { + return analysisResult{}, xerrors.Errorf("pom resolve error: %w", err) } - // Inherit values/properties from parent - pom.inherit(parent) - - // Generate properties + // Resolve dependencies props := pom.properties() - - // dependencyManagements have the next priority: - // 1. Managed dependencies from this POM - // 2. Managed dependencies from parent of this POM - depManagement := p.mergeDependencyManagements(pom.content.DependencyManagement.Dependencies.Dependency, - parent.dependencyManagement) - - // Merge dependencies. Child dependencies must be preferred than parent dependencies. - // Parents don't have to resolve dependencies. + depManagement := pom.content.DependencyManagement.Dependencies.Dependency deps := p.parseDependencies(pom.content.Dependencies.Dependency, props, depManagement, opts) - deps = p.mergeDependencies(parent.dependencies, deps, opts.exclusions) + deps = p.filterDependencies(deps, opts.exclusions) return analysisResult{ filePath: pom.filePath, @@ -388,6 +362,39 @@ func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) }, nil } +// resolveParent resolves its parent POMs and inherits properties, dependencies, and dependencyManagement. +func (p *Parser) resolveParent(pom *pom) error { + if pom.nil() { + return nil + } + + // Parse parent POM + parent, err := p.parseParent(pom.filePath, pom.content.Parent) + if err != nil { + return xerrors.Errorf("parent error: %w", err) + } + + // Inherit values/properties from parent + pom.inherit(parent) + + // Merge properties + pom.content.Properties = p.mergeProperties(pom.content.Properties, parent.content.Properties) + + // Merge dependencyManagement with the following priority: + // 1. Managed dependencies from this POM + // 2. Managed dependencies from parent of this POM + pom.content.DependencyManagement.Dependencies.Dependency = p.mergeDependencyManagements( + pom.content.DependencyManagement.Dependencies.Dependency, + parent.content.DependencyManagement.Dependencies.Dependency) + + // Merge dependencies + pom.content.Dependencies.Dependency = p.mergeDependencies( + pom.content.Dependencies.Dependency, + parent.content.Dependencies.Dependency) + + return nil +} + func (p *Parser) mergeDependencyManagements(depManagements ...[]pomDependency) []pomDependency { uniq := make(map[string]struct{}) var depManagement []pomDependency @@ -463,22 +470,20 @@ func (p *Parser) resolveDepManagement(props map[string]string, depManagement []p return newDepManagement } -func (p *Parser) mergeDependencies(parent, child []artifact, exclusions map[string]struct{}) []artifact { - var deps []artifact - unique := make(map[string]struct{}) +func (p *Parser) mergeProperties(child, parent properties) properties { + return lo.Assign(parent, child) +} - for _, d := range append(child, parent...) { - if excludeDep(exclusions, d) { - continue - } - if _, ok := unique[d.Name()]; ok { - continue - } - unique[d.Name()] = struct{}{} - deps = append(deps, d) - } +func (p *Parser) mergeDependencies(child, parent []pomDependency) []pomDependency { + return lo.UniqBy(append(child, parent...), func(d pomDependency) string { + return d.Name() + }) +} - return deps +func (p *Parser) filterDependencies(artifacts []artifact, exclusions map[string]struct{}) []artifact { + return lo.Filter(artifacts, func(art artifact, _ int) bool { + return !excludeDep(exclusions, art) + }) } func excludeDep(exclusions map[string]struct{}, art artifact) bool { @@ -497,38 +502,29 @@ func excludeDep(exclusions map[string]struct{}, art artifact) bool { return false } -func (p *Parser) parseParent(currentPath string, parent pomParent, rootDepManagement []pomDependency) (analysisResult, error) { +func (p *Parser) parseParent(currentPath string, parent pomParent) (*pom, error) { // Pass nil properties so that variables in are not evaluated. target := newArtifact(parent.GroupId, parent.ArtifactId, parent.Version, nil, nil) // if version is property (e.g. ${revision}) - we still need to parse this pom if target.IsEmpty() && !isProperty(parent.Version) { - return analysisResult{}, nil + return &pom{content: &pomXML{}}, nil } logger := p.logger.With("artifact", target.String()) logger.Debug("Start parent") defer logger.Debug("Exit parent") - // If the artifact is found in cache, it is returned. - if result := p.cache.get(target); result != nil { - return *result, nil - } - parentPOM, err := p.retrieveParent(currentPath, parent.RelativePath, target) if err != nil { logger.Debug("Parent POM not found", log.Err(err)) + return &pom{content: &pomXML{}}, nil } - result, err := p.analyze(parentPOM, analysisOptions{ - depManagement: rootDepManagement, - }) - if err != nil { - return analysisResult{}, xerrors.Errorf("analyze error: %w", err) + if err = p.resolveParent(parentPOM); err != nil { + return nil, xerrors.Errorf("parent pom resolve error: %w", err) } - p.cache.put(target, result) - - return result, nil + return parentPOM, nil } func (p *Parser) retrieveParent(currentPath, relativePath string, target artifact) (*pom, error) { @@ -565,7 +561,7 @@ func (p *Parser) retrieveParent(currentPath, relativePath string, target artifac } func (p *Parser) tryRelativePath(parentArtifact artifact, currentPath, relativePath string) (*pom, error) { - pom, err := p.openRelativePom(currentPath, relativePath) + parsedPOM, err := p.openRelativePom(currentPath, relativePath) if err != nil { return nil, err } @@ -576,19 +572,18 @@ func (p *Parser) tryRelativePath(parentArtifact artifact, currentPath, relativeP // But GroupID can be inherited from parent (`p.analyze` function is required to get the GroupID). // Version can contain a property (`p.analyze` function is required to get the GroupID). // So we can only match ArtifactID's. - if pom.artifact().ArtifactID != parentArtifact.ArtifactID { + if parsedPOM.artifact().ArtifactID != parentArtifact.ArtifactID { return nil, xerrors.New("'parent.relativePath' points at wrong local POM") } - result, err := p.analyze(pom, analysisOptions{}) - if err != nil { + if err := p.resolveParent(parsedPOM); err != nil { return nil, xerrors.Errorf("analyze error: %w", err) } - if !parentArtifact.Equal(result.artifact) { + if !parentArtifact.Equal(parsedPOM.artifact()) { return nil, xerrors.New("'parent.relativePath' points at wrong local POM") } - return pom, nil + return parsedPOM, nil } func (p *Parser) openRelativePom(currentPath, relativePath string) (*pom, error) { @@ -620,7 +615,7 @@ func (p *Parser) openPom(filePath string) (*pom, error) { } defer f.Close() - content, err := parsePom(f) + content, err := parsePom(f, false) if err != nil { return nil, xerrors.Errorf("failed to parse the local POM: %w", err) } @@ -777,7 +772,7 @@ func (p *Parser) fetchPOMFromRemoteRepository(repo string, paths []string) (*pom } defer resp.Body.Close() - content, err := parsePom(resp.Body) + content, err := parsePom(resp.Body, false) if err != nil { return nil, xerrors.Errorf("failed to parse the remote POM: %w", err) } @@ -788,13 +783,19 @@ func (p *Parser) fetchPOMFromRemoteRepository(repo string, paths []string) (*pom }, nil } -func parsePom(r io.Reader) (*pomXML, error) { +func parsePom(r io.Reader, lineNumber bool) (*pomXML, error) { parsed := &pomXML{} decoder := xml.NewDecoder(r) decoder.CharsetReader = charset.NewReaderLabel if err := decoder.Decode(parsed); err != nil { return nil, xerrors.Errorf("xml decode error: %w", err) } + if !lineNumber { + for i := range parsed.Dependencies.Dependency { + parsed.Dependencies.Dependency[i].StartLine = 0 + parsed.Dependencies.Dependency[i].EndLine = 0 + } + } return parsed, nil } diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index 82604846a4f3..7b77c0a7ef5e 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -14,6 +14,100 @@ import ( ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" ) +var ( + exampleNestedScopeCompile = func(start, end int) ftypes.Package { + var location ftypes.Locations + if start != 0 && end != 0 { + location = append(location, ftypes.Location{ + StartLine: start, + EndLine: end, + }) + } + return ftypes.Package{ + ID: "org.example:example-nested-scope-compile:1.0.0", + Name: "org.example:example-nested-scope-compile", + Version: "1.0.0", + Relationship: ftypes.RelationshipDirect, + Locations: location, + } + } + + exampleNestedScopeEmpty = func(start, end int) ftypes.Package { + var location ftypes.Locations + if start != 0 && end != 0 { + location = append(location, ftypes.Location{ + StartLine: start, + EndLine: end, + }) + } + return ftypes.Package{ + ID: "org.example:example-nested-scope-empty:1.0.0", + Name: "org.example:example-nested-scope-empty", + Version: "1.0.0", + Relationship: ftypes.RelationshipDirect, + Locations: location, + } + } + + exampleNestedScopeRuntime = func(start, end int) ftypes.Package { + var location ftypes.Locations + if start != 0 && end != 0 { + location = append(location, ftypes.Location{ + StartLine: start, + EndLine: end, + }) + } + return ftypes.Package{ + ID: "org.example:example-nested-scope-runtime:1.0.0", + Name: "org.example:example-nested-scope-runtime", + Version: "1.0.0", + Relationship: ftypes.RelationshipDirect, + Locations: location, + } + } + + exampleScopeCompile = ftypes.Package{ + ID: "org.example:example-scope-compile:2.0.0", + Name: "org.example:example-scope-compile", + Version: "2.0.0", + Relationship: ftypes.RelationshipIndirect, + } + + exampleScopeEmpty = ftypes.Package{ + ID: "org.example:example-scope-empty:2.0.0", + Name: "org.example:example-scope-empty", + Version: "2.0.0", + Relationship: ftypes.RelationshipIndirect, + } + + exampleScopeRuntime = ftypes.Package{ + ID: "org.example:example-scope-runtime:2.0.0", + Name: "org.example:example-scope-runtime", + Version: "2.0.0", + Relationship: ftypes.RelationshipIndirect, + } + exampleApiCompile = ftypes.Package{ + ID: "org.example:example-api-compile:3.0.0", + Name: "org.example:example-api-compile", + Version: "3.0.0", + Relationship: ftypes.RelationshipIndirect, + } + + exampleApiEmpty = ftypes.Package{ + ID: "org.example:example-api-empty:3.0.0", + Name: "org.example:example-api-empty", + Version: "3.0.0", + Relationship: ftypes.RelationshipIndirect, + } + + exampleApiRuntime = ftypes.Package{ + ID: "org.example:example-api-runtime:3.0.0", + Name: "org.example:example-api-runtime", + Version: "3.0.0", + Relationship: ftypes.RelationshipIndirect, + } +) + func TestPom_Parse(t *testing.T) { tests := []struct { name string @@ -1630,6 +1724,256 @@ func TestPom_Parse(t *testing.T) { }, }, }, + // [INFO] com.example:child-depManagement-in-parent:jar:1.0.0 + // [INFO] +- org.example:example-api2:jar:1.0.2:runtime + // [INFO] +- org.example:example-api3:jar:4.0.3:compile + // [INFO] \- org.example:example-api:jar:1.0.1:compile + { + name: "dependency from parent uses version from child(scanned) pom depManagement", + inputFile: filepath.Join("testdata", "use-child-dep-management-in-parent", "pom.xml"), + local: true, + want: []ftypes.Package{ + { + ID: "com.example:child-depManagement-in-parent:1.0.0", + Name: "com.example:child-depManagement-in-parent", + Version: "1.0.0", + Relationship: ftypes.RelationshipRoot, + }, + { + ID: "org.example:example-api:1.0.1", + Name: "org.example:example-api", + Version: "1.0.1", + Relationship: ftypes.RelationshipDirect, + }, + { + ID: "org.example:example-api2:1.0.2", + Name: "org.example:example-api2", + Version: "1.0.2", + Relationship: ftypes.RelationshipDirect, + }, + { + ID: "org.example:example-api3:4.0.3", + Name: "org.example:example-api3", + Version: "4.0.3", + Relationship: ftypes.RelationshipDirect, + }, + }, + wantDeps: []ftypes.Dependency{ + { + ID: "com.example:child-depManagement-in-parent:1.0.0", + DependsOn: []string{ + "org.example:example-api2:1.0.2", + "org.example:example-api3:4.0.3", + "org.example:example-api:1.0.1", + }, + }, + }, + }, + // [INFO] com.example:inherit-scopes-from-child-deps-and-their-parents:jar:0.0.1 + // [INFO] +- org.example:example-nested-scope-runtime:jar:1.0.0:runtime + // [INFO] | \- org.example:example-scope-runtime:jar:2.0.0:runtime + // [INFO] | \- org.example:example-api-runtime:jar:3.0.0:runtime + // [INFO] +- org.example:example-nested-scope-compile:jar:1.0.0:compile + // [INFO] | \- org.example:example-scope-compile:jar:2.0.0:compile + // [INFO] | \- org.example:example-api-compile:jar:3.0.0:compile + // [INFO] \- org.example:example-nested-scope-empty:jar:1.0.0:compile + // [INFO] \- org.example:example-scope-empty:jar:2.0.0:compile + // [INFO] \- org.example:example-api-empty:jar:3.0.0:compile + // + // `example-nested-*" dependencies and their parents contain `dependencyManagement` with changed scopes + { + name: "inherit scopes from child dependencies and their parents", + inputFile: filepath.Join("testdata", "inherit-scopes-from-child-deps-and-their-parents", "pom.xml"), + local: true, + want: []ftypes.Package{ + { + ID: "com.example:inherit-scopes-from-child-deps-and-their-parents:0.0.1", + Name: "com.example:inherit-scopes-from-child-deps-and-their-parents", + Version: "0.0.1", + Relationship: ftypes.RelationshipRoot, + }, + exampleNestedScopeCompile(16, 21), + exampleNestedScopeEmpty(22, 26), + exampleNestedScopeRuntime(10, 15), + exampleApiCompile, + exampleApiEmpty, + exampleApiRuntime, + exampleScopeCompile, + exampleScopeEmpty, + exampleScopeRuntime, + }, + wantDeps: []ftypes.Dependency{ + { + ID: "com.example:inherit-scopes-from-child-deps-and-their-parents:0.0.1", + DependsOn: []string{ + "org.example:example-nested-scope-compile:1.0.0", + "org.example:example-nested-scope-empty:1.0.0", + "org.example:example-nested-scope-runtime:1.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-compile:1.0.0", + DependsOn: []string{ + "org.example:example-scope-compile:2.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-empty:1.0.0", + DependsOn: []string{ + "org.example:example-scope-empty:2.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-runtime:1.0.0", + DependsOn: []string{ + "org.example:example-scope-runtime:2.0.0", + }, + }, + { + ID: "org.example:example-scope-compile:2.0.0", + DependsOn: []string{ + "org.example:example-api-compile:3.0.0", + }, + }, + { + ID: "org.example:example-scope-empty:2.0.0", + DependsOn: []string{ + "org.example:example-api-empty:3.0.0", + }, + }, + { + ID: "org.example:example-scope-runtime:2.0.0", + DependsOn: []string{ + "org.example:example-api-runtime:3.0.0", + }, + }, + }, + }, + // [INFO] com.example:inherit-scopes-in-parents-from-root:jar:0.1.0 + // [INFO] +- org.example:example-nested-scope-runtime:jar:1.0.0:runtime + // [INFO] | \- org.example:example-scope-runtime:jar:2.0.0:compile + // [INFO] | \- org.example:example-api-runtime:jar:3.0.0:runtime + // [INFO] +- org.example:example-nested-scope-compile:jar:1.0.0:compile + // [INFO] | \- org.example:example-scope-compile:jar:2.0.0:runtime + // [INFO] | \- org.example:example-api-compile:jar:3.0.0:test + // [INFO] \- org.example:example-nested-scope-empty:jar:1.0.0:compile + // [INFO] \- org.example:example-scope-empty:jar:2.0.0:runtime + // [INFO] \- org.example:example-api-empty:jar:3.0.0:test + // + // `example-nested-*" dependencies and their parents contain `dependencyManagement` with changed scopes + // scopes from `dependencyManagement` of root pom are used + { + name: "inherit scopes in children from root pom", + inputFile: filepath.Join("testdata", "inherit-scopes-in-children-from-root", "pom.xml"), + local: true, + want: []ftypes.Package{ + { + ID: "com.example:inherit-scopes-in-children-from-root:0.0.1", + Name: "com.example:inherit-scopes-in-children-from-root", + Version: "0.0.1", + Relationship: ftypes.RelationshipRoot, + }, + exampleNestedScopeCompile(51, 56), + exampleNestedScopeEmpty(57, 61), + exampleNestedScopeRuntime(45, 50), + exampleApiRuntime, + exampleScopeCompile, + exampleScopeEmpty, + exampleScopeRuntime, + }, + wantDeps: []ftypes.Dependency{ + { + ID: "com.example:inherit-scopes-in-children-from-root:0.0.1", + DependsOn: []string{ + "org.example:example-nested-scope-compile:1.0.0", + "org.example:example-nested-scope-empty:1.0.0", + "org.example:example-nested-scope-runtime:1.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-compile:1.0.0", + DependsOn: []string{ + "org.example:example-scope-compile:2.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-empty:1.0.0", + DependsOn: []string{ + "org.example:example-scope-empty:2.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-runtime:1.0.0", + DependsOn: []string{ + "org.example:example-scope-runtime:2.0.0", + }, + }, + { + ID: "org.example:example-scope-runtime:2.0.0", + DependsOn: []string{ + "org.example:example-api-runtime:3.0.0", + }, + }, + }, + }, + // [INFO] com.example:inherit-scopes-in-parents-from-root:jar:0.1.0 + // [INFO] +- org.example:example-nested-scope-runtime:jar:1.0.0:runtime + // [INFO] | \- org.example:example-scope-runtime:jar:2.0.0:compile + // [INFO] | \- org.example:example-api-runtime:jar:3.0.0:runtime + // [INFO] +- org.example:example-nested-scope-compile:jar:1.0.0:compile + // [INFO] | \- org.example:example-scope-compile:jar:2.0.0:runtime + // [INFO] | \- org.example:example-api-compile:jar:3.0.0:test + // [INFO] \- org.example:example-nested-scope-empty:jar:1.0.0:test + // [INFO] \- org.example:example-scope-empty:jar:2.0.0:test + // [INFO] \- org.example:example-api-empty:jar:3.0.0:test + // + // `example-nested-*" dependencies and their parents contain `dependencyManagement` with changed scopes + // scopes from `dependencyManagement` of root pom are used in parent dependencies + { + name: "inherit scopes in parent from root pom", + inputFile: filepath.Join("testdata", "inherit-scopes-in-parents-from-root", "pom.xml"), + local: true, + want: []ftypes.Package{ + { + ID: "com.example:inherit-scopes-in-parents-from-root:0.1.0", + Name: "com.example:inherit-scopes-in-parents-from-root", + Version: "0.1.0", + Relationship: ftypes.RelationshipRoot, + }, + exampleNestedScopeCompile(0, 0), + exampleNestedScopeRuntime(0, 0), + exampleApiRuntime, + exampleScopeCompile, + exampleScopeRuntime, + }, + wantDeps: []ftypes.Dependency{ + { + ID: "com.example:inherit-scopes-in-parents-from-root:0.1.0", + DependsOn: []string{ + "org.example:example-nested-scope-compile:1.0.0", + "org.example:example-nested-scope-runtime:1.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-compile:1.0.0", + DependsOn: []string{ + "org.example:example-scope-compile:2.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-runtime:1.0.0", + DependsOn: []string{ + "org.example:example-scope-runtime:2.0.0", + }, + }, + { + ID: "org.example:example-scope-runtime:2.0.0", + DependsOn: []string{ + "org.example:example-api-runtime:3.0.0", + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/dependency/parser/java/pom/pom.go b/pkg/dependency/parser/java/pom/pom.go index 889d107c3c6c..83c5d4fec609 100644 --- a/pkg/dependency/parser/java/pom/pom.go +++ b/pkg/dependency/parser/java/pom/pom.go @@ -23,11 +23,18 @@ type pom struct { content *pomXML } -func (p *pom) inherit(result analysisResult) { +func (p *pom) nil() bool { + return p == nil || p.content == nil +} + +func (p *pom) inherit(parent *pom) { + if parent == nil { + return + } // Merge properties - p.content.Properties = utils.MergeMaps(result.properties, p.content.Properties) + p.content.Properties = utils.MergeMaps(parent.properties(), p.content.Properties) - art := p.artifact().Inherit(result.artifact) + art := p.artifact().Inherit(parent.artifact()) p.content.GroupId = art.GroupID p.content.ArtifactId = art.ArtifactID @@ -40,12 +47,12 @@ func (p *pom) inherit(result analysisResult) { } } -func (p pom) properties() properties { +func (p *pom) properties() properties { props := p.content.Properties return utils.MergeMaps(props, p.projectProperties()) } -func (p pom) projectProperties() map[string]string { +func (p *pom) projectProperties() map[string]string { val := reflect.ValueOf(p.content).Elem() props := p.listProperties(val) @@ -73,7 +80,7 @@ func (p pom) projectProperties() map[string]string { return projectProperties } -func (p pom) listProperties(val reflect.Value) map[string]string { +func (p *pom) listProperties(val reflect.Value) map[string]string { props := make(map[string]string) for i := 0; i < val.NumField(); i++ { f := val.Type().Field(i) @@ -106,17 +113,17 @@ func (p pom) listProperties(val reflect.Value) map[string]string { return props } -func (p pom) artifact() artifact { +func (p *pom) artifact() artifact { return newArtifact(p.content.GroupId, p.content.ArtifactId, p.content.Version, p.licenses(), p.content.Properties) } -func (p pom) licenses() []string { +func (p *pom) licenses() []string { return slices.ZeroToNil(lo.FilterMap(p.content.Licenses.License, func(lic pomLicense, _ int) (string, bool) { return lic.Name, lic.Name != "" })) } -func (p pom) repositories(servers []Server) ([]string, []string) { +func (p *pom) repositories(servers []Server) ([]string, []string) { logger := log.WithPrefix("pom") var releaseRepos, snapshotRepos []string for _, rep := range p.content.Repositories.Repository { @@ -242,9 +249,11 @@ func (d pomDependency) Resolve(props map[string]string, depManagement, rootDepMa if managed.Version != "" { dep.Version = evaluateVariable(managed.Version, props, nil) } + if managed.Scope != "" { dep.Scope = evaluateVariable(managed.Scope, props, nil) } + if managed.Optional { dep.Optional = managed.Optional } @@ -287,7 +296,7 @@ func (d pomDependency) ToArtifact(opts analysisOptions) artifact { } var locations ftypes.Locations - if opts.lineNumber { + if d.StartLine != 0 && d.EndLine != 0 { locations = ftypes.Locations{ { StartLine: d.StartLine, diff --git a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-from-child-deps-and-their-parents/pom.xml b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-from-child-deps-and-their-parents/pom.xml new file mode 100644 index 000000000000..17e6c55de090 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-from-child-deps-and-their-parents/pom.xml @@ -0,0 +1,29 @@ + + 4.0.0 + + com.example + inherit-scopes-from-child-deps-and-their-parents + 0.0.1 + + + + org.example + example-nested-scope-runtime + 1.0.0 + runtime + + + org.example + example-nested-scope-compile + 1.0.0 + compile + + + org.example + example-nested-scope-empty + 1.0.0 + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-children-from-root/pom.xml b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-children-from-root/pom.xml new file mode 100644 index 000000000000..26bdb25621d7 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-children-from-root/pom.xml @@ -0,0 +1,64 @@ + + 4.0.0 + + com.example + inherit-scopes-in-children-from-root + 0.0.1 + + + + + org.example + example-scope-runtime + 2.0.0 + compile + + + org.example + example-scope-compile + 2.0.0 + runtime + + + org.example + example-api-compile + 3.0.0 + test + + + org.example + example-scope-empty + 2.0.0 + runtime + + + org.example + example-api-empty + 3.0.0 + test + + + + + + + org.example + example-nested-scope-runtime + 1.0.0 + runtime + + + org.example + example-nested-scope-compile + 1.0.0 + compile + + + org.example + example-nested-scope-empty + 1.0.0 + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/parent/pom.xml new file mode 100644 index 000000000000..dad0101e3f25 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/parent/pom.xml @@ -0,0 +1,77 @@ + + 4.0.0 + + com.example + inherit-scopes-in-parents-from-root-parent + 0.0.1 + pom + + + + + org.example + example-scope-runtime + 2.0.0 + compile + + + org.example + example-scope-compile + 2.0.0 + runtime + + + org.example + example-api-compile + 3.0.0 + test + + + org.example + example-scope-empty + 2.0.0 + test + + + org.example + example-api-empty + 3.0.0 + test + + + org.example + example-nested-scope-compile + 1.0.0 + runtime + + + org.example + example-nested-scope-empty + 1.0.0 + compile + + + + + + + org.example + example-nested-scope-runtime + 1.0.0 + runtime + + + org.example + example-nested-scope-compile + 1.0.0 + compile + + + org.example + example-nested-scope-empty + 1.0.0 + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/pom.xml b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/pom.xml new file mode 100644 index 000000000000..45ef37785e60 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/pom.xml @@ -0,0 +1,39 @@ + + 4.0.0 + + com.example + inherit-scopes-in-parents-from-root + 0.1.0 + + + com.example + inherit-scopes-in-parents-from-root-parent + 0.0.1 + ./parent + + + + + + org.example + example-nested-scope-runtime + 1.0.0 + test + + + org.example + example-nested-scope-compile + 1.0.0 + test + + + org.example + example-nested-scope-empty + 1.0.0 + test + + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/example-nested-scope-compile-1.0.0.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/example-nested-scope-compile-1.0.0.pom new file mode 100644 index 000000000000..43ca478a88cd --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/example-nested-scope-compile-1.0.0.pom @@ -0,0 +1,41 @@ + + + + 4.0.0 + + + com.example + example-nested-parent-scope-compile + 1.0.1 + ./parent + + + org.example + example-nested-scope-compile + 1.0.0 + + jar + Example pom with example-scope-compile 2.0.0 + + + + + org.example + example-api-compile + 3.0.0 + runtime + + + + + + + org.example + example-scope-compile + 2.0.0 + compile + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/parent/pom.xml new file mode 100644 index 000000000000..5fe41b350df1 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/parent/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + + com.example + example-nested-parent-scope-compile + 1.0.1 + pom + + + + + org.example + example-scope-compile + 2.0.0 + test + + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/example-nested-scope-empty-1.0.0.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/example-nested-scope-empty-1.0.0.pom new file mode 100644 index 000000000000..b1def2383f79 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/example-nested-scope-empty-1.0.0.pom @@ -0,0 +1,40 @@ + + + + 4.0.0 + + + com.example + example-nested-parent-scope-empty + 1.0.1 + ./parent + + + org.example + example-nested-scope-empty + 1.0.0 + + jar + Example pom with example-scope-empty 2.0.0 + + + + + org.example + example-api-empty + 3.0.0 + test + + + + + + + org.example + example-scope-empty + 2.0.0 + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/parent/pom.xml new file mode 100644 index 000000000000..6ca0232f4fc3 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/parent/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + + com.example + example-nested-parent-scope-empty + 1.0.1 + pom + + + + + org.example + example-scope-empty + 2.0.0 + compile + + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/example-nested-scope-runtime-1.0.0.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/example-nested-scope-runtime-1.0.0.pom new file mode 100644 index 000000000000..8e48dcd812c3 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/example-nested-scope-runtime-1.0.0.pom @@ -0,0 +1,41 @@ + + + + 4.0.0 + + + com.example + example-nested-parent-scope-runtime + 1.0.1 + ./parent + + + org.example + example-nested-scope-runtime + 1.0.0 + + jar + Example pom with example-scope-runtime 2.0.0 + + + + + org.example + example-api-runtime + 3.0.0 + test + + + + + + + org.example + example-scope-runtime + 2.0.0 + runtime + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/parent/pom.xml new file mode 100644 index 000000000000..f59df7902390 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/parent/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + + com.example + example-nested-parent-scope-runtime + 1.0.1 + pom + + + + + org.example + example-scope-runtime + 2.0.0 + test + + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-compile/2.0.0/example-scope-compile-2.0.0.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-compile/2.0.0/example-scope-compile-2.0.0.pom new file mode 100644 index 000000000000..1d5bc02ff3b9 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-compile/2.0.0/example-scope-compile-2.0.0.pom @@ -0,0 +1,23 @@ + + + + 4.0.0 + + org.example + example-scope-compile + 2.0.0 + + jar + Example pom with example-api-compile 3.0.0 + + + + org.example + example-api-compile + 3.0.0 + compile + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-empty/2.0.0/example-scope-empty-2.0.0.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-empty/2.0.0/example-scope-empty-2.0.0.pom new file mode 100644 index 000000000000..82ce31008fc3 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-empty/2.0.0/example-scope-empty-2.0.0.pom @@ -0,0 +1,22 @@ + + + + 4.0.0 + + org.example + example-scope-empty + 2.0.0 + + jar + Example pom with example-api-empty 3.0.0 + + + + org.example + example-api-empty + 3.0.0 + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-runtime/2.0.0/example-scope-runtime-2.0.0.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-runtime/2.0.0/example-scope-runtime-2.0.0.pom new file mode 100644 index 000000000000..90bf973def80 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-runtime/2.0.0/example-scope-runtime-2.0.0.pom @@ -0,0 +1,23 @@ + + + + 4.0.0 + + org.example + example-scope-runtime + 2.0.0 + + jar + Example pom with example-api-runtime 3.0.0 + + + + org.example + example-api-runtime + 3.0.0 + runtime + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/transitive-parents/base/pom.xml b/pkg/dependency/parser/java/pom/testdata/transitive-parents/base/pom.xml index 5662c0c9e8de..ae1d6ced6e3f 100644 --- a/pkg/dependency/parser/java/pom/testdata/transitive-parents/base/pom.xml +++ b/pkg/dependency/parser/java/pom/testdata/transitive-parents/base/pom.xml @@ -13,7 +13,7 @@ com.example parent 3.0.0 - ../parent + ../ diff --git a/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml new file mode 100644 index 000000000000..dec887e6eecc --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml @@ -0,0 +1,34 @@ + + + + 4.0.0 + + + org.example + example-top-parent + 5.0.0 + ../top-parent/pom.xml + + + org.example + example-parent + 4.0.0 + pom + + + 4.0.1 + + + + org.example + example-api2 + + + org.example + example-api3 + 4.0.3 + compile + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/pom.xml new file mode 100644 index 000000000000..651fbba9f885 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/pom.xml @@ -0,0 +1,45 @@ + + 4.0.0 + + + org.example + example-parent + 4.0.0 + ./parent/pom.xml + + + com.example + child-depManagement-in-parent + 1.0.0 + + + + 1.0.1 + 1.0.2 + 1.0.3 + + + + + + org.example + example-api + ${api.version} + runtime + + + org.example + example-api2 + ${api2.version} + runtime + + + org.example + example-api3 + ${api3.version} + runtime + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/top-parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/top-parent/pom.xml new file mode 100644 index 000000000000..84d8954a4bf9 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/top-parent/pom.xml @@ -0,0 +1,34 @@ + + + + 4.0.0 + + org.example + example-top-parent + 5.0.0 + pom + + + 5.0.1 + + + + + org.example + example-api + ${api.version} + compile + + + org.example + example-api2 + + + org.example + example-api3 + 5.0.3 + compile + + + \ No newline at end of file From 922949a43ea21b10858962330ef8d8297ff40b0a Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Thu, 17 Oct 2024 12:12:44 +0400 Subject: [PATCH 54/94] test: use forked images (#7755) Signed-off-by: knqyf263 --- integration/testimages.ini | 4 ++-- pkg/attestation/attestation_test.go | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/integration/testimages.ini b/integration/testimages.ini index 1a7b8ef1a0c0..778fbc9b8e63 100644 --- a/integration/testimages.ini +++ b/integration/testimages.ini @@ -1,3 +1,3 @@ # Configuration file for both shell scripts and Go programs -TEST_IMAGES=ghcr.io/aquasecurity/trivy-test-images -TEST_VM_IMAGES=ghcr.io/aquasecurity/trivy-test-vm-images +TEST_IMAGES=ghcr.io/knqyf263/trivy-test-images +TEST_VM_IMAGES=ghcr.io/knqyf263/trivy-test-vm-images diff --git a/pkg/attestation/attestation_test.go b/pkg/attestation/attestation_test.go index de75b5676692..0233ba30cf78 100644 --- a/pkg/attestation/attestation_test.go +++ b/pkg/attestation/attestation_test.go @@ -9,7 +9,6 @@ import ( slsa "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common" "github.com/stretchr/testify/require" - "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/attestation" ) @@ -28,7 +27,7 @@ func TestStatement_UnmarshalJSON(t *testing.T) { PredicateType: "cosign.sigstore.dev/attestation/v1", Subject: []in_toto.Subject{ { - Name: testutil.ImageName("", "", ""), + Name: "ghcr.io/aquasecurity/trivy-test-images", // Defined in the attestations.json file Digest: slsa.DigestSet{ "sha256": "72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb", }, From a7baa93b00b8636aa097e64cdb8eed97dbd68511 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 17 Oct 2024 11:35:09 +0200 Subject: [PATCH 55/94] feat(parser): ignore white space in pom.xml files (#7747) Signed-off-by: Samuel Gaist --- pkg/dependency/parser/java/pom/artifact.go | 2 +- pkg/dependency/parser/java/pom/parse_test.go | 64 +++++++++++++++++++ .../java/pom/testdata/with-spaces/pom.xml | 31 +++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 pkg/dependency/parser/java/pom/testdata/with-spaces/pom.xml diff --git a/pkg/dependency/parser/java/pom/artifact.go b/pkg/dependency/parser/java/pom/artifact.go index 73ebe6b21407..8fc20b236b51 100644 --- a/pkg/dependency/parser/java/pom/artifact.go +++ b/pkg/dependency/parser/java/pom/artifact.go @@ -163,7 +163,7 @@ func evaluateVariable(s string, props map[string]string, seenProps []string) str } s = strings.ReplaceAll(s, m[0], newValue) } - return s + return strings.TrimSpace(s) } func printLoopedPropertiesStack(env string, usedProps []string) { diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index 7b77c0a7ef5e..8d0bf002d6dc 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -1974,6 +1974,70 @@ func TestPom_Parse(t *testing.T) { }, }, }, + //[INFO] com.example:root-pom-with-spaces:jar:1.0.0 + //[INFO] \- org.example:example-nested:jar:3.3.3:compile + //[INFO] \- org.example:example-dependency:jar:1.2.4:compile + //[INFO] \- org.example:example-api:jar:2.0.0:compile + { + name: "space at the start and/or end of the text nodes", + inputFile: filepath.Join("testdata", "with-spaces", "pom.xml"), + local: true, + want: []ftypes.Package{ + { + ID: "com.example:root-pom-with-spaces:1.0.0", + Name: "com.example:root-pom-with-spaces", + Version: "1.0.0", + Relationship: ftypes.RelationshipRoot, + }, + { + ID: "org.example:example-nested:3.3.3", + Name: "org.example:example-nested", + Version: "3.3.3", + Relationship: ftypes.RelationshipDirect, + Locations: ftypes.Locations{ + { + StartLine: 24, + EndLine: 28, + }, + }, + }, + { + ID: "org.example:example-api:2.0.0", + Name: "org.example:example-api", + Version: "2.0.0", + Licenses: []string{"The Apache Software License, Version 2.0"}, + Relationship: ftypes.RelationshipIndirect, + }, + // dependency version is taken from `com.example:root-pom-with-spaces` from dependencyManagement + // not from `com.example:example-nested` from `com.example:example-nested` + { + ID: "org.example:example-dependency:1.2.4", + Name: "org.example:example-dependency", + Version: "1.2.4", + Relationship: ftypes.RelationshipIndirect, + }, + }, + wantDeps: []ftypes.Dependency{ + { + ID: "com.example:root-pom-with-spaces:1.0.0", + DependsOn: []string{ + "org.example:example-nested:3.3.3", + }, + }, + { + ID: "org.example:example-dependency:1.2.4", + DependsOn: []string{ + "org.example:example-api:2.0.0", + }, + }, + { + ID: "org.example:example-nested:3.3.3", + DependsOn: []string{ + "org.example:example-dependency:1.2.4", + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/dependency/parser/java/pom/testdata/with-spaces/pom.xml b/pkg/dependency/parser/java/pom/testdata/with-spaces/pom.xml new file mode 100644 index 000000000000..7a0a1013aa31 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/with-spaces/pom.xml @@ -0,0 +1,31 @@ + + 4.0.0 + + com.example + root-pom-with-spaces + 1.0.0 + + + 1.2.4 + + + + + + org.example + example-dependency + ${dependency.version} + + + + + + + org.example + example-nested + 3.3.3 + + + + From cd44bb48f8ff3cca20bb9b4c6ab3dce1907fc528 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Fri, 18 Oct 2024 03:50:12 +0600 Subject: [PATCH 56/94] refactor(misconf): simplify k8s scanner (#7717) Signed-off-by: nikpivkin --- pkg/iac/scanners/helm/scanner.go | 2 +- pkg/iac/scanners/kubernetes/parser/parser.go | 57 +- pkg/iac/scanners/kubernetes/scanner.go | 112 +--- pkg/iac/scanners/kubernetes/scanner_test.go | 666 ++++--------------- 4 files changed, 132 insertions(+), 705 deletions(-) diff --git a/pkg/iac/scanners/helm/scanner.go b/pkg/iac/scanners/helm/scanner.go index bfa63a5d2c00..daf8f3108628 100644 --- a/pkg/iac/scanners/helm/scanner.go +++ b/pkg/iac/scanners/helm/scanner.go @@ -130,7 +130,7 @@ func (s *Scanner) getScanResults(path string, ctx context.Context, target fs.FS) file := file s.logger.Debug("Processing rendered chart file", log.FilePath(file.TemplateFilePath)) - manifests, err := kparser.New().Parse(strings.NewReader(file.ManifestContent), file.TemplateFilePath) + manifests, err := kparser.Parse(ctx, strings.NewReader(file.ManifestContent), file.TemplateFilePath) if err != nil { return nil, fmt.Errorf("unmarshal yaml: %w", err) } diff --git a/pkg/iac/scanners/kubernetes/parser/parser.go b/pkg/iac/scanners/kubernetes/parser/parser.go index f3ca7d613562..57d723801c98 100644 --- a/pkg/iac/scanners/kubernetes/parser/parser.go +++ b/pkg/iac/scanners/kubernetes/parser/parser.go @@ -5,69 +5,14 @@ import ( "encoding/json" "fmt" "io" - "io/fs" - "path/filepath" "regexp" "strings" "gopkg.in/yaml.v3" kyaml "sigs.k8s.io/yaml" - - "github.com/aquasecurity/trivy/pkg/log" ) -type Parser struct { - logger *log.Logger -} - -// New creates a new K8s parser -func New() *Parser { - return &Parser{ - logger: log.WithPrefix("k8s parser"), - } -} - -func (p *Parser) ParseFS(ctx context.Context, target fs.FS, path string) (map[string][]any, error) { - files := make(map[string][]any) - if err := fs.WalkDir(target, filepath.ToSlash(path), func(path string, entry fs.DirEntry, err error) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - if err != nil { - return err - } - if entry.IsDir() { - return nil - } - - parsed, err := p.ParseFile(ctx, target, path) - if err != nil { - p.logger.Error("Parse error", log.FilePath(path), log.Err(err)) - return nil - } - - files[path] = parsed - return nil - }); err != nil { - return nil, err - } - return files, nil -} - -// ParseFile parses Kubernetes manifest from the provided filesystem path. -func (p *Parser) ParseFile(_ context.Context, fsys fs.FS, path string) ([]any, error) { - f, err := fsys.Open(filepath.ToSlash(path)) - if err != nil { - return nil, err - } - defer func() { _ = f.Close() }() - return p.Parse(f, path) -} - -func (p *Parser) Parse(r io.Reader, path string) ([]any, error) { - +func Parse(_ context.Context, r io.Reader, path string) ([]any, error) { contents, err := io.ReadAll(r) if err != nil { return nil, err diff --git a/pkg/iac/scanners/kubernetes/scanner.go b/pkg/iac/scanners/kubernetes/scanner.go index dfd248cc8b1d..f79d59aaaf12 100644 --- a/pkg/iac/scanners/kubernetes/scanner.go +++ b/pkg/iac/scanners/kubernetes/scanner.go @@ -3,119 +3,17 @@ package kubernetes import ( "context" "io" - "io/fs" - "path/filepath" - "sort" - "sync" - "github.com/liamg/memoryfs" - - "github.com/aquasecurity/trivy/pkg/iac/framework" - "github.com/aquasecurity/trivy/pkg/iac/rego" - "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners" + "github.com/aquasecurity/trivy/pkg/iac/scanners/generic" "github.com/aquasecurity/trivy/pkg/iac/scanners/kubernetes/parser" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" "github.com/aquasecurity/trivy/pkg/iac/types" - "github.com/aquasecurity/trivy/pkg/log" ) -var _ scanners.FSScanner = (*Scanner)(nil) -var _ options.ConfigurableScanner = (*Scanner)(nil) - -type Scanner struct { - mu sync.Mutex - logger *log.Logger - options []options.ScannerOption - regoScanner *rego.Scanner - parser *parser.Parser -} - -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetRegoOnly(bool) {} -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} - -func NewScanner(opts ...options.ScannerOption) *Scanner { - s := &Scanner{ - options: opts, - logger: log.WithPrefix("k8s scanner"), - parser: parser.New(), - } - for _, opt := range opts { - opt(s) - } - return s -} - -func (s *Scanner) Name() string { - return "Kubernetes" -} - -func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { - s.mu.Lock() - defer s.mu.Unlock() - if s.regoScanner != nil { - return s.regoScanner, nil - } - regoScanner := rego.NewScanner(types.SourceKubernetes, s.options...) - if err := regoScanner.LoadPolicies(srcFS); err != nil { - return nil, err - } - s.regoScanner = regoScanner - return regoScanner, nil +func NewScanner(opts ...options.ScannerOption) *generic.GenericScanner { + return generic.NewScanner("Kubernetes", types.SourceKubernetes, generic.ParseFunc(parse), opts...) } -func (s *Scanner) ScanReader(ctx context.Context, filename string, reader io.Reader) (scan.Results, error) { - memfs := memoryfs.New() - if err := memfs.MkdirAll(filepath.Base(filename), 0o700); err != nil { - return nil, err - } - data, err := io.ReadAll(reader) - if err != nil { - return nil, err - } - if err := memfs.WriteFile(filename, data, 0o644); err != nil { - return nil, err - } - return s.ScanFS(ctx, memfs, ".") -} - -func (s *Scanner) ScanFS(ctx context.Context, target fs.FS, dir string) (scan.Results, error) { - - k8sFilesets, err := s.parser.ParseFS(ctx, target, dir) - if err != nil { - return nil, err - } - - if len(k8sFilesets) == 0 { - return nil, nil - } - - var inputs []rego.Input - for path, k8sFiles := range k8sFilesets { - for _, content := range k8sFiles { - inputs = append(inputs, rego.Input{ - Path: path, - FS: target, - Contents: content, - }) - } - } - - regoScanner, err := s.initRegoScanner(target) - if err != nil { - return nil, err - } - - s.logger.Debug("Scanning files", log.Int("count", len(inputs))) - results, err := regoScanner.ScanInput(ctx, inputs...) - if err != nil { - return nil, err - } - results.SetSourceAndFilesystem("", target, false) - - sort.Slice(results, func(i, j int) bool { - return results[i].Rule().AVDID < results[j].Rule().AVDID - }) - return results, nil +func parse(ctx context.Context, r io.Reader, path string) (any, error) { + return parser.Parse(ctx, r, path) } diff --git a/pkg/iac/scanners/kubernetes/scanner_test.go b/pkg/iac/scanners/kubernetes/scanner_test.go index ef1ac38560f4..c9186a7f9c40 100644 --- a/pkg/iac/scanners/kubernetes/scanner_test.go +++ b/pkg/iac/scanners/kubernetes/scanner_test.go @@ -1,24 +1,23 @@ -package kubernetes +package kubernetes_test import ( "context" - "os" + "io/fs" "strings" "testing" + "testing/fstest" + "github.com/samber/lo" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/aquasecurity/trivy/internal/testutil" - "github.com/aquasecurity/trivy/pkg/iac/framework" "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" + "github.com/aquasecurity/trivy/pkg/iac/scanners/kubernetes" ) -func Test_BasicScan_YAML(t *testing.T) { - - fs := testutil.CreateFS(t, map[string]string{ - "/code/example.yaml": ` +func Test_ScanYAML(t *testing.T) { + file := ` apiVersion: v1 kind: Pod metadata: @@ -28,148 +27,48 @@ spec: - command: ["sh", "-c", "echo 'Hello' && sleep 1h"] image: busybox name: hello -`, - "/rules/rule.rego": ` +` + fsys := buildFS(map[string]string{ + "code/example.yaml": file, + "checks/rule.rego": `# METADATA +# title: test check +# custom: +# id: KSV011 +# avd_id: AVD-KSV-0011 +# severity: LOW +# input: +# selector: +# - type: kubernetes package builtin.kubernetes.KSV011 import data.lib.kubernetes -import data.lib.utils - -default failLimitsCPU = false - -__rego_metadata__ := { - "id": "KSV011", - "avd_id": "AVD-KSV-0011", - "title": "CPU not limited", - "short_code": "limit-cpu", - "version": "v1.0.0", - "severity": "LOW", - "type": "Kubernetes Security Check", - "description": "Enforcing CPU limits prevents DoS via resource exhaustion.", - "recommended_actions": "Set a limit value under 'containers[].resources.limits.cpu'.", - "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-resource-requests-and-limits", -} - -__rego_input__ := { - "combine": false, - "selector": [{"type": "kubernetes"}], -} - -# getLimitsCPUContainers returns all containers which have set resources.limits.cpu -getLimitsCPUContainers[container] { - allContainers := kubernetes.containers[_] - utils.has_key(allContainers.resources.limits, "cpu") - container := allContainers.name -} - -# getNoLimitsCPUContainers returns all containers which have not set -# resources.limits.cpu -getNoLimitsCPUContainers[container] { - container := kubernetes.containers[_].name - not getLimitsCPUContainers[container] -} - -# failLimitsCPU is true if containers[].resources.limits.cpu is not set -# for ANY container -failLimitsCPU { - count(getNoLimitsCPUContainers) > 0 -} deny[res] { - failLimitsCPU - - msg := kubernetes.format(sprintf("Container '%s' of %s '%s' should set 'resources.limits.cpu'", [getNoLimitsCPUContainers[_], kubernetes.kind, kubernetes.name])) - - res := { - "msg": msg, - "id": __rego_metadata__.id, - "title": __rego_metadata__.title, - "severity": __rego_metadata__.severity, - "type": __rego_metadata__.type, - "startline": 6, - "endline": 10, - } + container := kubernetes.containers[_] + res := result.new("fail", container) } `, }) - scanner := NewScanner( - rego.WithPolicyDirs("rules"), + scanner := kubernetes.NewScanner( + rego.WithPolicyFilesystem(fsys), + rego.WithPolicyDirs("checks"), rego.WithEmbeddedLibraries(true), ) - results, err := scanner.ScanFS(context.TODO(), fs, "code") + results, err := scanner.ScanFS(context.TODO(), fsys, "code") require.NoError(t, err) - require.Len(t, results.GetFailed(), 1) - - assert.Equal(t, scan.Rule{ - AVDID: "AVD-KSV-0011", - Aliases: []string{"KSV011"}, - ShortCode: "limit-cpu", - Summary: "CPU not limited", - Explanation: "Enforcing CPU limits prevents DoS via resource exhaustion.", - Impact: "", - Resolution: "Set a limit value under 'containers[].resources.limits.cpu'.", - Provider: "kubernetes", - Service: "general", - Links: []string{"https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-resource-requests-and-limits"}, - Severity: "LOW", - Terraform: &scan.EngineMetadata{}, - CloudFormation: &scan.EngineMetadata{}, - CustomChecks: scan.CustomChecks{Terraform: (*scan.TerraformCustomCheck)(nil)}, - RegoPackage: "data.builtin.kubernetes.KSV011", - Frameworks: map[framework.Framework][]string{ - framework.Default: {}, - }, - }, results.GetFailed()[0].Rule()) + failed := results.GetFailed() + require.Len(t, failed, 1) - failure := results.GetFailed()[0] - actualCode, err := failure.GetCode() - require.NoError(t, err) - for i := range actualCode.Lines { - actualCode.Lines[i].Highlighted = "" - } - assert.Equal(t, []scan.Line{ - { - Number: 6, - Content: "spec: ", - IsCause: true, - FirstCause: true, - Annotation: "", - }, - { - Number: 7, - Content: " containers: ", - IsCause: true, - Annotation: "", - }, - { - Number: 8, - Content: " - command: [\"sh\", \"-c\", \"echo 'Hello' && sleep 1h\"]", - IsCause: true, - Annotation: "", - }, - { - Number: 9, - Content: " image: busybox", - IsCause: true, - Annotation: "", - }, - { - Number: 10, - Content: " name: hello", - IsCause: true, - LastCause: true, - Annotation: "", - }, - }, actualCode.Lines) + assert.Equal(t, "AVD-KSV-0011", failed[0].Rule().AVDID) + assertLines(t, file, failed) } -func Test_BasicScan_JSON(t *testing.T) { +func Test_ScanJSON(t *testing.T) { - fs := testutil.CreateFS(t, map[string]string{ - "/code/example.json": ` + file := ` { "apiVersion": "v1", "kind": "Pod", @@ -190,165 +89,58 @@ func Test_BasicScan_JSON(t *testing.T) { ] } } -`, - "/rules/rule.rego": ` +` + + fsys := buildFS(map[string]string{ + "code/example.json": file, + "checks/rule.rego": `# METADATA +# title: test check +# custom: +# id: KSV011 +# avd_id: AVD-KSV-0011 +# severity: LOW +# input: +# selector: +# - type: kubernetes package builtin.kubernetes.KSV011 import data.lib.kubernetes -import data.lib.utils - -default failLimitsCPU = false - -__rego_metadata__ := { - "id": "KSV011", - "avd_id": "AVD-KSV-0011", - "title": "CPU not limited", - "short_code": "limit-cpu", - "version": "v1.0.0", - "severity": "LOW", - "type": "Kubernetes Security Check", - "description": "Enforcing CPU limits prevents DoS via resource exhaustion.", - "recommended_actions": "Set a limit value under 'containers[].resources.limits.cpu'.", - "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-resource-requests-and-limits", -} - -__rego_input__ := { - "combine": false, - "selector": [{"type": "kubernetes"}], -} - -# getLimitsCPUContainers returns all containers which have set resources.limits.cpu -getLimitsCPUContainers[container] { - allContainers := kubernetes.containers[_] - utils.has_key(allContainers.resources.limits, "cpu") - container := allContainers.name -} - -# getNoLimitsCPUContainers returns all containers which have not set -# resources.limits.cpu -getNoLimitsCPUContainers[container] { - container := kubernetes.containers[_].name - not getLimitsCPUContainers[container] -} - -# failLimitsCPU is true if containers[].resources.limits.cpu is not set -# for ANY container -failLimitsCPU { - count(getNoLimitsCPUContainers) > 0 -} deny[res] { - failLimitsCPU - - msg := kubernetes.format(sprintf("Container '%s' of %s '%s' should set 'resources.limits.cpu'", [getNoLimitsCPUContainers[_], kubernetes.kind, kubernetes.name])) - - res := { - "msg": msg, - "id": __rego_metadata__.id, - "title": __rego_metadata__.title, - "severity": __rego_metadata__.severity, - "type": __rego_metadata__.type, - "startline": 6, - "endline": 10, - } + container := kubernetes.containers[_] + res := result.new("fail", container) } `, }) - scanner := NewScanner( - rego.WithPolicyDirs("rules"), + scanner := kubernetes.NewScanner( + rego.WithPolicyFilesystem(fsys), + rego.WithPolicyDirs("checks"), rego.WithEmbeddedLibraries(true), ) - results, err := scanner.ScanFS(context.TODO(), fs, "code") + results, err := scanner.ScanFS(context.TODO(), fsys, "code") require.NoError(t, err) require.Len(t, results.GetFailed(), 1) - assert.Equal(t, scan.Rule{ - AVDID: "AVD-KSV-0011", - Aliases: []string{"KSV011"}, - ShortCode: "limit-cpu", - Summary: "CPU not limited", - Explanation: "Enforcing CPU limits prevents DoS via resource exhaustion.", - Impact: "", - Resolution: "Set a limit value under 'containers[].resources.limits.cpu'.", - Provider: "kubernetes", - Service: "general", - Links: []string{"https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-resource-requests-and-limits"}, - Severity: "LOW", - Terraform: &scan.EngineMetadata{}, - CloudFormation: &scan.EngineMetadata{}, - CustomChecks: scan.CustomChecks{Terraform: (*scan.TerraformCustomCheck)(nil)}, - RegoPackage: "data.builtin.kubernetes.KSV011", - Frameworks: map[framework.Framework][]string{ - framework.Default: {}, - }, - }, results.GetFailed()[0].Rule()) + failed := results.GetFailed() + require.Len(t, failed, 1) - failure := results.GetFailed()[0] - actualCode, err := failure.GetCode() - require.NoError(t, err) - for i := range actualCode.Lines { - actualCode.Lines[i].Highlighted = "" - } - assert.Equal(t, []scan.Line{ - { - Number: 6, - Content: ` "name": "hello-cpu-limit"`, - IsCause: true, - FirstCause: true, - Annotation: "", - }, - { - Number: 7, - Content: ` },`, - IsCause: true, - Annotation: "", - }, - { - Number: 8, - Content: ` "spec": {`, - IsCause: true, - Annotation: "", - }, - { - Number: 9, - Content: ` "containers": [`, - IsCause: true, - Annotation: "", - }, - { - Number: 10, - Content: ` {`, - IsCause: true, - LastCause: true, - Annotation: "", - }, - }, actualCode.Lines) + assert.Equal(t, "AVD-KSV-0011", failed[0].Rule().AVDID) + assertLines(t, file, failed) } -func Test_FileScan(t *testing.T) { +func Test_YamlWithSeparator(t *testing.T) { - results, err := NewScanner(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true), rego.WithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(` -apiVersion: v1 -kind: Pod -metadata: - name: hello-cpu-limit -spec: - containers: - - command: ["sh", "-c", "echo 'Hello' && sleep 1h"] - image: busybox - name: hello -`)) - require.NoError(t, err) - - assert.NotEmpty(t, results.GetFailed()) -} - -func Test_FileScan_WithSeparator(t *testing.T) { + fsys := buildFS(map[string]string{ + "check.rego": `package defsec - results, err := NewScanner(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(` +deny[res] { + input.kind == "Pod" + res := result.new("fail", input) +}`, + "k8s.yaml": ` --- --- apiVersion: v1 @@ -360,13 +152,21 @@ spec: - command: ["sh", "-c", "echo 'Hello' && sleep 1h"] image: busybox name: hello -`)) +`, + }) + + scanner := kubernetes.NewScanner( + rego.WithPolicyFilesystem(fsys), + rego.WithPolicyDirs("."), + rego.WithEmbeddedLibraries(true), + ) + results, err := scanner.ScanFS(context.TODO(), fsys, ".") require.NoError(t, err) assert.NotEmpty(t, results.GetFailed()) } -func Test_FileScan_MultiManifests(t *testing.T) { +func Test_YamlMultiDocument(t *testing.T) { file := ` --- apiVersion: v1 @@ -389,306 +189,71 @@ spec: image: busybox name: hello2 ` - - results, err := NewScanner( - rego.WithEmbeddedPolicies(true), - rego.WithEmbeddedLibraries(true), - rego.WithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(file)) - require.NoError(t, err) - - assert.Greater(t, len(results.GetFailed()), 1) - fileLines := strings.Split(file, "\n") - for _, failure := range results.GetFailed() { - actualCode, err := failure.GetCode() - require.NoError(t, err) - assert.NotEmpty(t, actualCode.Lines) - for _, line := range actualCode.Lines { - assert.Greater(t, len(fileLines), line.Number) - assert.Equal(t, line.Content, fileLines[line.Number-1]) - } - } -} - -func Test_FileScanWithPolicyReader(t *testing.T) { - - results, err := NewScanner(rego.WithPolicyReader(strings.NewReader(`package defsec - -deny[msg] { - msg = "fail" -} -`))).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(` -apiVersion: v1 -kind: Pod -metadata: - name: hello-cpu-limit -spec: - containers: - - command: ["sh", "-c", "echo 'Hello' && sleep 1h"] - image: busybox - name: hello -`)) - require.NoError(t, err) - - assert.Len(t, results.GetFailed(), 1) -} - -func Test_FileScanJSON(t *testing.T) { - - results, err := NewScanner(rego.WithPolicyReader(strings.NewReader(`package defsec - -deny[msg] { - input.kind == "Pod" - msg = "fail" -} -`))).ScanReader(context.TODO(), "k8s.json", strings.NewReader(` -{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "mongo", - "labels": { - "name": "mongo", - "role": "mongo" - } - }, - "spec": { - "volumes": [ - { - "name": "mongo-disk", - "gcePersistentDisk": { - "pdName": "mongo-disk", - "fsType": "ext4" - } - } - ], - "containers": [ - { - "name": "mongo", - "image": "mongo:latest", - "ports": [ - { - "name": "mongo", - "containerPort": 27017 - } - ], - "volumeMounts": [ - { - "name": "mongo-disk", - "mountPath": "/data/db" - } - ] - } - ] - } -} -`)) - require.NoError(t, err) - - assert.Len(t, results.GetFailed(), 1) -} - -func Test_FileScanWithMetadata(t *testing.T) { - - results, err := NewScanner( - rego.WithTrace(os.Stdout), - rego.WithPolicyReader(strings.NewReader(`package defsec - -deny[msg] { - input.kind == "Pod" - msg := { - "msg": "fail", - "startline": 2, - "endline": 2, - "filepath": "chartname/template/serviceAccount.yaml" - } -} -`))).ScanReader( - context.TODO(), - "k8s.yaml", - strings.NewReader(` -apiVersion: v1 -kind: Pod -metadata: - name: hello-cpu-limit -spec: - containers: - - command: ["sh", "-c", "echo 'Hello' && sleep 1h"] - image: busybox - name: hello -`)) - require.NoError(t, err) - - assert.NotEmpty(t, results.GetFailed()) - - firstResult := results.GetFailed()[0] - assert.Equal(t, 2, firstResult.Metadata().Range().GetStartLine()) - assert.Equal(t, 2, firstResult.Metadata().Range().GetEndLine()) - assert.Equal(t, "chartname/template/serviceAccount.yaml", firstResult.Metadata().Range().GetFilename()) -} - -func Test_FileScanExampleWithResultFunction(t *testing.T) { - - results, err := NewScanner( - rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true), - rego.WithPolicyReader(strings.NewReader(`package defsec - -import data.lib.kubernetes - -default checkCapsDropAll = false - -__rego_metadata__ := { -"id": "KSV003", -"avd_id": "AVD-KSV-0003", -"title": "Default capabilities not dropped", -"short_code": "drop-default-capabilities", -"version": "v1.0.0", -"severity": "LOW", -"type": "Kubernetes Security Check", -"description": "The container should drop all default capabilities and add only those that are needed for its execution.", -"recommended_actions": "Add 'ALL' to containers[].securityContext.capabilities.drop.", -"url": "https://kubesec.io/basics/containers-securitycontext-capabilities-drop-index-all/", -} - -__rego_input__ := { -"combine": false, -"selector": [{"type": "kubernetes"}], -} - -# Get all containers which include 'ALL' in security.capabilities.drop -getCapsDropAllContainers[container] { -allContainers := kubernetes.containers[_] -lower(allContainers.securityContext.capabilities.drop[_]) == "all" -container := allContainers.name -} - -# Get all containers which don't include 'ALL' in security.capabilities.drop -getCapsNoDropAllContainers[container] { -container := kubernetes.containers[_] -not getCapsDropAllContainers[container.name] -} + fsys := buildFS(map[string]string{ + "check.rego": `package defsec deny[res] { -output := getCapsNoDropAllContainers[_] - -msg := kubernetes.format(sprintf("Container '%s' of %s '%s' should add 'ALL' to 'securityContext.capabilities.drop'", [output.name, kubernetes.kind, kubernetes.name])) + input.kind == "Pod" + res := result.new("fail", input) +}`, + "k8s.yaml": file, + }) -res := result.new(msg, output) -} + scanner := kubernetes.NewScanner( + rego.WithPolicyFilesystem(fsys), + rego.WithPolicyDirs("."), + rego.WithEmbeddedLibraries(true), + ) -`))).ScanReader( - context.TODO(), - "k8s.yaml", - strings.NewReader(` -apiVersion: v1 -kind: Pod -metadata: - name: hello-cpu-limit -spec: - containers: - - command: ["sh", "-c", "echo 'Hello' && sleep 1h"] - image: busybox - name: hello - securityContext: - capabilities: - drop: - - nothing -`)) + results, err := scanner.ScanFS(context.TODO(), fsys, ".") require.NoError(t, err) - require.NotEmpty(t, results.GetFailed()) - - firstResult := results.GetFailed()[0] - assert.Equal(t, 8, firstResult.Metadata().Range().GetStartLine()) - assert.Equal(t, 14, firstResult.Metadata().Range().GetEndLine()) - assert.Equal(t, "k8s.yaml", firstResult.Metadata().Range().GetFilename()) + assertLines(t, file, results) } -func Test_checkPolicyIsApplicable(t *testing.T) { - srcFS := testutil.CreateFS(t, map[string]string{ - "policies/pod_policy.rego": `# METADATA -# title: "Process can elevate its own privileges" -# description: "A program inside the container can elevate its own privileges and run as root, which might give the program control over the container and node." +func Test_CheckWithSubtype(t *testing.T) { + fsys := buildFS(map[string]string{ + "checks/pod_policy.rego": `# METADATA +# title: test check # scope: package # schemas: # - input: schema["kubernetes"] -# related_resources: -# - https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted # custom: # id: KSV001 -# avd_id: AVD-KSV-0999 +# avd_id: AVD-KSV-0001 # severity: MEDIUM -# short_code: no-self-privesc -# recommended_action: "Set 'set containers[].securityContext.allowPrivilegeEscalation' to 'false'." # input: # selector: # - type: kubernetes # subtypes: # - kind: Pod -package builtin.kubernetes.KSV999 +package builtin.kubernetes.KSV001 import data.lib.kubernetes -import data.lib.utils - -default checkAllowPrivilegeEscalation = false - -# getNoPrivilegeEscalationContainers returns the names of all containers which have -# securityContext.allowPrivilegeEscalation set to false. -getNoPrivilegeEscalationContainers[container] { - allContainers := kubernetes.containers[_] - allContainers.securityContext.allowPrivilegeEscalation == false - container := allContainers.name -} - -# getPrivilegeEscalationContainers returns the names of all containers which have -# securityContext.allowPrivilegeEscalation set to true or not set. -getPrivilegeEscalationContainers[container] { - containerName := kubernetes.containers[_].name - not getNoPrivilegeEscalationContainers[containerName] - container := kubernetes.containers[_] -} deny[res] { - output := getPrivilegeEscalationContainers[_] - msg := kubernetes.format(sprintf("Container '%s' of %s '%s' should set 'securityContext.allowPrivilegeEscalation' to false", [output.name, kubernetes.kind, kubernetes.name])) - res := result.new(msg, output) + res := result.new("fail", input) } - `, - "policies/namespace_policy.rego": `# METADATA -# title: "The default namespace should not be used" -# description: "ensure that default namespace should not be used" + "checks/namespace_policy.rego": `# METADATA +# title: test check 2 # scope: package # schemas: # - input: schema["kubernetes"] -# related_resources: -# - https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ # custom: -# id: KSV110 -# avd_id: AVD-KSV-0888 +# id: KSV002 +# avd_id: AVD-KSV-0002 # severity: LOW -# short_code: default-namespace-should-not-be-used -# recommended_action: "Ensure that namespaces are created to allow for appropriate segregation of Kubernetes resources and that all new resources are created in a specific namespace." # input: # selector: # - type: kubernetes # subtypes: # - kind: Namespace -package builtin.kubernetes.KSV888 - -import data.lib.kubernetes - -default defaultNamespaceInUse = false - -defaultNamespaceInUse { - kubernetes.namespace == "default" -} +package builtin.kubernetes.KSV002 deny[res] { - defaultNamespaceInUse - msg := sprintf("%s '%s' should not be set with 'default' namespace", [kubernetes.kind, kubernetes.name]) - res := result.new(msg, input.metadata.namespace) + res := result.new("fail", input) } - `, "test/KSV001/pod.yaml": `apiVersion: v1 kind: Pod @@ -706,18 +271,37 @@ spec: `, }) - scanner := NewScanner( - // rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true), + scanner := kubernetes.NewScanner( rego.WithEmbeddedLibraries(true), - rego.WithPolicyDirs("policies/"), - rego.WithPolicyFilesystem(srcFS), + rego.WithPolicyDirs("checks"), + rego.WithPolicyFilesystem(fsys), ) - results, err := scanner.ScanFS(context.TODO(), srcFS, "test/KSV001") + results, err := scanner.ScanFS(context.TODO(), fsys, "test/KSV001") require.NoError(t, err) require.NoError(t, err) require.Len(t, results.GetFailed(), 1) - failure := results.GetFailed()[0].Rule() - assert.Equal(t, "Process can elevate its own privileges", failure.Summary) + failure := results.GetFailed()[0] + + assert.Equal(t, "AVD-KSV-0001", failure.Rule().AVDID) +} + +func assertLines(t *testing.T, content string, results scan.Results) { + lines := strings.Split(content, "\n") + for _, res := range results { + actualCode, err := res.GetCode() + require.NoError(t, err) + assert.NotEmpty(t, actualCode.Lines) + for _, line := range actualCode.Lines { + assert.Greater(t, len(lines), line.Number) + assert.Equal(t, line.Content, lines[line.Number-1]) + } + } +} + +func buildFS(files map[string]string) fs.FS { + return fstest.MapFS(lo.MapValues(files, func(val string, _ string) *fstest.MapFile { + return &fstest.MapFile{Data: []byte(val)} + })) } From 35fd018ae7ad86823f114f0ac2f1376726aee444 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Fri, 18 Oct 2024 10:45:24 +0600 Subject: [PATCH 57/94] fix(misconf): fix for Azure Storage Account network acls adaptation (#7602) Signed-off-by: nikpivkin --- pkg/iac/adapters/arm/storage/adapt.go | 24 ++++++++++----------- pkg/iac/adapters/arm/storage/adapt_test.go | 25 ++++++++++++++++++---- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/pkg/iac/adapters/arm/storage/adapt.go b/pkg/iac/adapters/arm/storage/adapt.go index 186ab5beda9d..26a0d10c8616 100644 --- a/pkg/iac/adapters/arm/storage/adapt.go +++ b/pkg/iac/adapters/arm/storage/adapt.go @@ -18,20 +18,18 @@ func adaptAccounts(deployment azure.Deployment) []storage.Account { var accounts []storage.Account for _, resource := range deployment.GetResourcesByType("Microsoft.Storage/storageAccounts") { - var networkRules []storage.NetworkRule - for _, acl := range resource.Properties.GetMapValue("networkAcls").AsList() { + acl := resource.Properties.GetMapValue("networkAcls") - var bypasses []types.StringValue - bypassProp := acl.GetMapValue("bypass") - for _, bypass := range strings.Split(bypassProp.AsString(), ",") { - bypasses = append(bypasses, types.String(bypass, bypassProp.GetMetadata())) - } + var bypasses []types.StringValue + bypassProp := acl.GetMapValue("bypass") + for _, bypass := range strings.Split(bypassProp.AsString(), ",") { + bypasses = append(bypasses, types.String(strings.TrimSpace(bypass), bypassProp.GetMetadata())) + } - networkRules = append(networkRules, storage.NetworkRule{ - Metadata: acl.GetMetadata(), - Bypass: bypasses, - AllowByDefault: types.Bool(acl.GetMapValue("defaultAction").EqualTo("Allow"), acl.GetMetadata()), - }) + networkRule := storage.NetworkRule{ + Metadata: acl.GetMetadata(), + Bypass: bypasses, + AllowByDefault: types.Bool(acl.GetMapValue("defaultAction").EqualTo("Allow"), acl.GetMetadata()), } var queues []storage.Queue @@ -52,7 +50,7 @@ func adaptAccounts(deployment azure.Deployment) []storage.Account { account := storage.Account{ Metadata: resource.Metadata, - NetworkRules: networkRules, + NetworkRules: []storage.NetworkRule{networkRule}, EnforceHTTPS: resource.Properties.GetMapValue("supportsHttpsTrafficOnly").AsBoolValue(false, resource.Properties.GetMetadata()), Containers: containers, QueueProperties: storage.QueueProperties{ diff --git a/pkg/iac/adapters/arm/storage/adapt_test.go b/pkg/iac/adapters/arm/storage/adapt_test.go index a6965ca1560c..372986f23529 100644 --- a/pkg/iac/adapters/arm/storage/adapt_test.go +++ b/pkg/iac/adapters/arm/storage/adapt_test.go @@ -6,6 +6,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/internal/testutil" + "github.com/aquasecurity/trivy/pkg/iac/providers/azure/storage" "github.com/aquasecurity/trivy/pkg/iac/scanners/azure" "github.com/aquasecurity/trivy/pkg/iac/types" ) @@ -43,6 +45,10 @@ func Test_AdaptStorage(t *testing.T) { "minimumTlsVersion": azure.NewValue("TLS1_2", types.NewTestMetadata()), "supportsHttpsTrafficOnly": azure.NewValue(true, types.NewTestMetadata()), "publicNetworkAccess": azure.NewValue("Disabled", types.NewTestMetadata()), + "networkAcls": azure.NewValue(map[string]azure.Value{ + "bypass": azure.NewValue("Logging, Metrics", types.NewTestMetadata()), + "defaultAction": azure.NewValue("Allow", types.NewTestMetadata()), + }, types.NewTestMetadata()), }, types.NewTestMetadata()), }, }, @@ -52,9 +58,20 @@ func Test_AdaptStorage(t *testing.T) { require.Len(t, output.Accounts, 1) - account := output.Accounts[0] - assert.Equal(t, "TLS1_2", account.MinimumTLSVersion.Value()) - assert.True(t, account.EnforceHTTPS.Value()) - assert.False(t, account.PublicNetworkAccess.Value()) + expected := storage.Storage{ + Accounts: []storage.Account{{ + MinimumTLSVersion: types.StringTest("TLS1_2"), + EnforceHTTPS: types.BoolTest(true), + PublicNetworkAccess: types.BoolTest(false), + NetworkRules: []storage.NetworkRule{{ + Bypass: []types.StringValue{ + types.StringTest("Logging"), + types.StringTest("Metrics"), + }, + AllowByDefault: types.BoolTest(true), + }}, + }}, + } + testutil.AssertDefsecEqual(t, expected, output) } From c225883649f58128a99fa2c1cef327d0e57940be Mon Sep 17 00:00:00 2001 From: Johannes Feichtner <343448+Churro@users.noreply.github.com> Date: Fri, 18 Oct 2024 09:10:46 +0200 Subject: [PATCH 58/94] feat(cyclonedx): add file checksums to `CycloneDX` reports (#7507) Co-authored-by: knqyf263 --- .../testdata/conda-cyclonedx.json.golden | 12 + ...fluentd-multiple-lockfiles.cdx.json.golden | 330 ++++++++++++++++++ pkg/commands/artifact/run.go | 4 +- 3 files changed, 344 insertions(+), 2 deletions(-) diff --git a/integration/testdata/conda-cyclonedx.json.golden b/integration/testdata/conda-cyclonedx.json.golden index 7f3a352fcce7..df8f575e9053 100644 --- a/integration/testdata/conda-cyclonedx.json.golden +++ b/integration/testdata/conda-cyclonedx.json.golden @@ -34,6 +34,12 @@ "type": "library", "name": "openssl", "version": "1.1.1q", + "hashes": [ + { + "alg": "SHA-1", + "content": "237db0da53131e4548cb1181337fa0f420299e1f" + } + ], "licenses": [ { "license": { @@ -58,6 +64,12 @@ "type": "library", "name": "pip", "version": "22.2.2", + "hashes": [ + { + "alg": "SHA-1", + "content": "a6a2db7668f1ad541d704369fc66c96a4415aa24" + } + ], "licenses": [ { "license": { diff --git a/integration/testdata/fluentd-multiple-lockfiles.cdx.json.golden b/integration/testdata/fluentd-multiple-lockfiles.cdx.json.golden index 65fc78e6c66f..9f23585a01da 100644 --- a/integration/testdata/fluentd-multiple-lockfiles.cdx.json.golden +++ b/integration/testdata/fluentd-multiple-lockfiles.cdx.json.golden @@ -6169,6 +6169,12 @@ "type": "library", "name": "activesupport", "version": "6.0.2.1", + "hashes": [ + { + "alg": "SHA-1", + "content": "a2cd09dcbaf8ca1951fb8e3f2ebdfe6728ab44f7" + } + ], "licenses": [ { "license": { @@ -6201,6 +6207,12 @@ "type": "library", "name": "addressable", "version": "2.7.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "b4596fdeffcb1c89b24623b6f775a6b054a8323f" + } + ], "licenses": [ { "license": { @@ -6233,6 +6245,12 @@ "type": "library", "name": "concurrent-ruby", "version": "1.1.6", + "hashes": [ + { + "alg": "SHA-1", + "content": "c96749b0390ad63300b13dca6fd83e5508facf18" + } + ], "licenses": [ { "license": { @@ -6265,6 +6283,12 @@ "type": "library", "name": "cool.io", "version": "1.6.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "706a2490b54301e8ae8f2ca8f9f56b279b96ac7b" + } + ], "purl": "pkg:gem/cool.io@1.6.0", "properties": [ { @@ -6290,6 +6314,12 @@ "type": "library", "name": "dig_rb", "version": "1.0.1", + "hashes": [ + { + "alg": "SHA-1", + "content": "04a4a555fe3a7e253098e870cf8a6c8746828829" + } + ], "licenses": [ { "license": { @@ -6322,6 +6352,12 @@ "type": "library", "name": "domain_name", "version": "0.5.20190701", + "hashes": [ + { + "alg": "SHA-1", + "content": "e45a352deedbf1d48c2563caa583d0864d6ac62b" + } + ], "licenses": [ { "license": { @@ -6364,6 +6400,12 @@ "type": "library", "name": "elasticsearch-api", "version": "7.5.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "aac794d1d845525dc57d73d8bd5bda4b7f593ea4" + } + ], "licenses": [ { "license": { @@ -6396,6 +6438,12 @@ "type": "library", "name": "elasticsearch-transport", "version": "7.5.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "29ab0a306cfc109b82ac19c37f288956a4d6d1d9" + } + ], "licenses": [ { "license": { @@ -6428,6 +6476,12 @@ "type": "library", "name": "elasticsearch", "version": "7.5.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "f3996e145e83f80d27ed48f8d2dca84f02c696c3" + } + ], "licenses": [ { "license": { @@ -6460,6 +6514,12 @@ "type": "library", "name": "excon", "version": "0.72.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "8b5c81a189d2748ae488dff8a7b4876493b86f76" + } + ], "licenses": [ { "license": { @@ -6492,6 +6552,12 @@ "type": "library", "name": "faraday", "version": "0.17.3", + "hashes": [ + { + "alg": "SHA-1", + "content": "b8c741fbdc2d729a59e2e855037421040673ca45" + } + ], "licenses": [ { "license": { @@ -6524,6 +6590,12 @@ "type": "library", "name": "ffi-compiler", "version": "1.0.1", + "hashes": [ + { + "alg": "SHA-1", + "content": "b9ffee214ef79e695c14c8703566f7c13be4c2ba" + } + ], "licenses": [ { "license": { @@ -6556,6 +6628,12 @@ "type": "library", "name": "ffi", "version": "1.12.2", + "hashes": [ + { + "alg": "SHA-1", + "content": "e6345da46b7a923b2248bc76d074362e7491376b" + } + ], "licenses": [ { "license": { @@ -6588,6 +6666,12 @@ "type": "library", "name": "fluent-plugin-concat", "version": "2.4.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "b6a0da88821e50d052cb244b57562f00abe79888" + } + ], "licenses": [ { "license": { @@ -6620,6 +6704,12 @@ "type": "library", "name": "fluent-plugin-detect-exceptions", "version": "0.0.13", + "hashes": [ + { + "alg": "SHA-1", + "content": "d1a7b50f7723ead908453f463e24424735be0a56" + } + ], "licenses": [ { "license": { @@ -6652,6 +6742,12 @@ "type": "library", "name": "fluent-plugin-elasticsearch", "version": "3.8.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "d60372f3af2757abd0a4ff68484e9328b2cbe386" + } + ], "licenses": [ { "license": { @@ -6684,6 +6780,12 @@ "type": "library", "name": "fluent-plugin-kubernetes_metadata_filter", "version": "2.4.1", + "hashes": [ + { + "alg": "SHA-1", + "content": "eeb3ce046c69c9c83ed1d4bc949058ef6a124f96" + } + ], "licenses": [ { "license": { @@ -6716,6 +6818,12 @@ "type": "library", "name": "fluent-plugin-multi-format-parser", "version": "1.0.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "9aa245fc07627474621e29f04507a377dfae09d3" + } + ], "licenses": [ { "license": { @@ -6748,6 +6856,12 @@ "type": "library", "name": "fluent-plugin-prometheus", "version": "1.7.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "597a311791f0d05968c558e8015c8bed864137e2" + } + ], "licenses": [ { "license": { @@ -6780,6 +6894,12 @@ "type": "library", "name": "fluent-plugin-systemd", "version": "1.0.2", + "hashes": [ + { + "alg": "SHA-1", + "content": "115901208913bc5031597a20fae33c50c6de6500" + } + ], "licenses": [ { "license": { @@ -6812,6 +6932,12 @@ "type": "library", "name": "fluentd", "version": "1.8.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "5f31ca316e345410e5a5b70b5fafed8a51fd5092" + } + ], "licenses": [ { "license": { @@ -6844,6 +6970,12 @@ "type": "library", "name": "http-accept", "version": "1.7.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "21dedf2ba79a24f86528c2dfc32d17dd9324d9fd" + } + ], "purl": "pkg:gem/http-accept@1.7.0", "properties": [ { @@ -6869,6 +7001,12 @@ "type": "library", "name": "http-cookie", "version": "1.0.3", + "hashes": [ + { + "alg": "SHA-1", + "content": "e6f5b8e237e694b3729797cca134525822769964" + } + ], "licenses": [ { "license": { @@ -6901,6 +7039,12 @@ "type": "library", "name": "http-form_data", "version": "2.2.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "53c844c1f954a9c43b78b8e57f18c0ec965beb1f" + } + ], "licenses": [ { "license": { @@ -6933,6 +7077,12 @@ "type": "library", "name": "http-parser", "version": "1.2.1", + "hashes": [ + { + "alg": "SHA-1", + "content": "7c6889d98755a1fe8859d850892412a0e001ba9a" + } + ], "licenses": [ { "license": { @@ -6965,6 +7115,12 @@ "type": "library", "name": "http", "version": "4.3.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "79032e0328aa1d3ee184a38c50cd93d5bce8998b" + } + ], "licenses": [ { "license": { @@ -6997,6 +7153,12 @@ "type": "library", "name": "http_parser.rb", "version": "0.6.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "0ed80e936eaf7151f540186333c3df436afd46c6" + } + ], "licenses": [ { "license": { @@ -7029,6 +7191,12 @@ "type": "library", "name": "i18n", "version": "1.8.2", + "hashes": [ + { + "alg": "SHA-1", + "content": "d13bccc2521cef33fc4303888b24f327a7369877" + } + ], "licenses": [ { "license": { @@ -7061,6 +7229,12 @@ "type": "library", "name": "kubeclient", "version": "4.6.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "31916cb42ac6b30c68a5422414946d0328be94d4" + } + ], "licenses": [ { "license": { @@ -7093,6 +7267,12 @@ "type": "library", "name": "lru_redux", "version": "1.1.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "c8c5874f406a8fefc655fee48b75dfa276a5b8fa" + } + ], "licenses": [ { "license": { @@ -7125,6 +7305,12 @@ "type": "library", "name": "mime-types-data", "version": "3.2019.1009", + "hashes": [ + { + "alg": "SHA-1", + "content": "8a80ce9bf4961df0184d25699612d29293a05aee" + } + ], "licenses": [ { "license": { @@ -7157,6 +7343,12 @@ "type": "library", "name": "mime-types", "version": "3.3.1", + "hashes": [ + { + "alg": "SHA-1", + "content": "b70aa1555acff548ee282c76ddd562e831483187" + } + ], "licenses": [ { "license": { @@ -7189,6 +7381,12 @@ "type": "library", "name": "minitest", "version": "5.14.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "8fcf25c201eacdf1a0e4db78efcb37ad590f33c0" + } + ], "licenses": [ { "license": { @@ -7221,6 +7419,12 @@ "type": "library", "name": "msgpack", "version": "1.3.3", + "hashes": [ + { + "alg": "SHA-1", + "content": "bda4ff6f3cd395534ba441ccacc4640f9dc43942" + } + ], "licenses": [ { "license": { @@ -7253,6 +7457,12 @@ "type": "library", "name": "multi_json", "version": "1.14.1", + "hashes": [ + { + "alg": "SHA-1", + "content": "fead333877a2db2e2aaca87d8cd1f270952cd42e" + } + ], "licenses": [ { "license": { @@ -7285,6 +7495,12 @@ "type": "library", "name": "multipart-post", "version": "2.1.1", + "hashes": [ + { + "alg": "SHA-1", + "content": "927edb51d5b23a49a417fe1503f196896c0e8034" + } + ], "licenses": [ { "license": { @@ -7317,6 +7533,12 @@ "type": "library", "name": "netrc", "version": "0.11.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "98d7bbb894429413feb5c0a3b766a7945f65e3ba" + } + ], "licenses": [ { "license": { @@ -7349,6 +7571,12 @@ "type": "library", "name": "oj", "version": "3.10.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "b348b933b9c2f6a6e952f6a15c7cbd9f1186815f" + } + ], "licenses": [ { "license": { @@ -7381,6 +7609,12 @@ "type": "library", "name": "prometheus-client", "version": "0.9.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "f829d25ee6b39cdda518f7b6f85be6563d7b5990" + } + ], "licenses": [ { "license": { @@ -7413,6 +7647,12 @@ "type": "library", "name": "public_suffix", "version": "4.0.3", + "hashes": [ + { + "alg": "SHA-1", + "content": "ac88907845a8bec2a0df25cf2e3ef61121e47252" + } + ], "licenses": [ { "license": { @@ -7445,6 +7685,12 @@ "type": "library", "name": "quantile", "version": "0.2.1", + "hashes": [ + { + "alg": "SHA-1", + "content": "07a0817cd9df688930b2d8481a647a7ec321b870" + } + ], "licenses": [ { "license": { @@ -7477,6 +7723,12 @@ "type": "library", "name": "rake", "version": "13.0.1", + "hashes": [ + { + "alg": "SHA-1", + "content": "d01a832a472daf914670adda88b44b419a4d2daf" + } + ], "licenses": [ { "license": { @@ -7509,6 +7761,12 @@ "type": "library", "name": "recursive-open-struct", "version": "1.1.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "5a4a02765d82d6786a832384b890f0a2497c2e14" + } + ], "licenses": [ { "license": { @@ -7541,6 +7799,12 @@ "type": "library", "name": "rest-client", "version": "2.1.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "a7e5943a216b16e0867693f20d5d1604cd015486" + } + ], "licenses": [ { "license": { @@ -7573,6 +7837,12 @@ "type": "library", "name": "serverengine", "version": "2.2.1", + "hashes": [ + { + "alg": "SHA-1", + "content": "16e5806b2d513f6b075355c602aed0f960584267" + } + ], "licenses": [ { "license": { @@ -7605,6 +7875,12 @@ "type": "library", "name": "sigdump", "version": "0.2.4", + "hashes": [ + { + "alg": "SHA-1", + "content": "1bae5c6042dc82a4bec6aacb42f75ba71f7cb634" + } + ], "licenses": [ { "license": { @@ -7637,6 +7913,12 @@ "type": "library", "name": "strptime", "version": "0.2.3", + "hashes": [ + { + "alg": "SHA-1", + "content": "17150d9e40754ea1a732796f224b9be78e77b86a" + } + ], "licenses": [ { "license": { @@ -7669,6 +7951,12 @@ "type": "library", "name": "systemd-journal", "version": "1.3.3", + "hashes": [ + { + "alg": "SHA-1", + "content": "4f310622fe58e95897147736c96d3d42174a3363" + } + ], "licenses": [ { "license": { @@ -7701,6 +7989,12 @@ "type": "library", "name": "thread_safe", "version": "0.3.6", + "hashes": [ + { + "alg": "SHA-1", + "content": "546993ac33864e279ae73e918d6da5d4ca083098" + } + ], "licenses": [ { "license": { @@ -7733,6 +8027,12 @@ "type": "library", "name": "tzinfo-data", "version": "1.2019.3", + "hashes": [ + { + "alg": "SHA-1", + "content": "26832d11382943b02433f3ad1df7653b4cfdf3a2" + } + ], "licenses": [ { "license": { @@ -7765,6 +8065,12 @@ "type": "library", "name": "tzinfo", "version": "1.2.6", + "hashes": [ + { + "alg": "SHA-1", + "content": "5b7db490d431d97366729086683e736d2b5fee99" + } + ], "licenses": [ { "license": { @@ -7797,6 +8103,12 @@ "type": "library", "name": "unf", "version": "0.1.4", + "hashes": [ + { + "alg": "SHA-1", + "content": "85ff87b60a6d16ffddf4db5f5f91c0ef76bacd3d" + } + ], "licenses": [ { "license": { @@ -7829,6 +8141,12 @@ "type": "library", "name": "unf_ext", "version": "0.0.7.6", + "hashes": [ + { + "alg": "SHA-1", + "content": "1b5141ee855f16e832534c2e73d81fec0601ebd3" + } + ], "licenses": [ { "license": { @@ -7861,6 +8179,12 @@ "type": "library", "name": "yajl-ruby", "version": "1.4.1", + "hashes": [ + { + "alg": "SHA-1", + "content": "670f3cd2fc601c9b7fde02b1d8c60e90491a7221" + } + ], "licenses": [ { "license": { @@ -7893,6 +8217,12 @@ "type": "library", "name": "zeitwerk", "version": "2.3.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "803894c06d28932016866a26fc2b22c4db942094" + } + ], "licenses": [ { "license": { diff --git a/pkg/commands/artifact/run.go b/pkg/commands/artifact/run.go index 49c7d3b34296..5018434d10c2 100644 --- a/pkg/commands/artifact/run.go +++ b/pkg/commands/artifact/run.go @@ -538,9 +538,9 @@ func (r *runner) initScannerConfig(ctx context.Context, opts flag.Options) (Scan } } - // SPDX needs to calculate digests for package files + // SPDX and CycloneDX need to calculate digests for package files var fileChecksum bool - if opts.Format == types.FormatSPDXJSON || opts.Format == types.FormatSPDX { + if opts.Format == types.FormatSPDXJSON || opts.Format == types.FormatSPDX || opts.Format == types.FormatCycloneDX { fileChecksum = true } From 8d5dbc9fec3569b22ed81a03c40eaf732768718b Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Sat, 19 Oct 2024 06:58:51 +0600 Subject: [PATCH 59/94] fix(misconf): properly expand dynamic blocks (#7612) Signed-off-by: nikpivkin Co-authored-by: Simar --- pkg/iac/scanners/terraform/module_test.go | 2 +- .../scanners/terraform/parser/evaluator.go | 49 +-- .../scanners/terraform/parser/parser_test.go | 400 +++++++++++------- pkg/iac/terraform/attribute.go | 9 +- pkg/iac/terraform/block.go | 163 ++++++- 5 files changed, 409 insertions(+), 214 deletions(-) diff --git a/pkg/iac/scanners/terraform/module_test.go b/pkg/iac/scanners/terraform/module_test.go index d0d289a9d562..ec4291fd59e4 100644 --- a/pkg/iac/scanners/terraform/module_test.go +++ b/pkg/iac/scanners/terraform/module_test.go @@ -567,7 +567,7 @@ resource "something" "else" { for_each = toset(["true"]) content { - ok = each.value + ok = blah.value } } } diff --git a/pkg/iac/scanners/terraform/parser/evaluator.go b/pkg/iac/scanners/terraform/parser/evaluator.go index 809498f35c63..8e2e737b5d9b 100644 --- a/pkg/iac/scanners/terraform/parser/evaluator.go +++ b/pkg/iac/scanners/terraform/parser/evaluator.go @@ -260,36 +260,17 @@ func (e *evaluator) evaluateSteps() { } func (e *evaluator) expandBlocks(blocks terraform.Blocks) terraform.Blocks { - return e.expandDynamicBlocks(e.expandBlockForEaches(e.expandBlockCounts(blocks), false)...) + return e.expandDynamicBlocks(e.expandBlockForEaches(e.expandBlockCounts(blocks))...) } func (e *evaluator) expandDynamicBlocks(blocks ...*terraform.Block) terraform.Blocks { for _, b := range blocks { - e.expandDynamicBlock(b) - } - return blocks -} - -func (e *evaluator) expandDynamicBlock(b *terraform.Block) { - for _, sub := range b.AllBlocks() { - e.expandDynamicBlock(sub) - } - for _, sub := range b.AllBlocks().OfType("dynamic") { - if sub.IsExpanded() { - continue - } - blockName := sub.TypeLabel() - expanded := e.expandBlockForEaches(terraform.Blocks{sub}, true) - for _, ex := range expanded { - if content := ex.GetBlock("content"); content.IsNotNil() { - _ = e.expandDynamicBlocks(content) - b.InjectBlock(content, blockName) - } - } - if len(expanded) > 0 { - sub.MarkExpanded() + if err := b.ExpandBlock(); err != nil { + e.logger.Error(`Failed to expand dynamic block.`, + log.String("block", b.FullName()), log.Err(err)) } } + return blocks } func isBlockSupportsForEachMetaArgument(block *terraform.Block) bool { @@ -297,11 +278,10 @@ func isBlockSupportsForEachMetaArgument(block *terraform.Block) bool { "module", "resource", "data", - "dynamic", }, block.Type()) } -func (e *evaluator) expandBlockForEaches(blocks terraform.Blocks, isDynamic bool) terraform.Blocks { +func (e *evaluator) expandBlockForEaches(blocks terraform.Blocks) terraform.Blocks { var forEachFiltered terraform.Blocks @@ -348,7 +328,7 @@ func (e *evaluator) expandBlockForEaches(blocks terraform.Blocks, isDynamic bool // is the value of the collection. The exception is the use of for-each inside a dynamic block, // because in this case the collection element may not be a primitive value. if (forEachVal.Type().IsCollectionType() || forEachVal.Type().IsTupleType()) && - !forEachVal.Type().IsMapType() && !isDynamic { + !forEachVal.Type().IsMapType() { stringVal, err := convert.Convert(val, cty.String) if err != nil { e.logger.Error( @@ -374,22 +354,7 @@ func (e *evaluator) expandBlockForEaches(blocks terraform.Blocks, isDynamic bool ctx.Set(eachObj, "each") ctx.Set(eachObj, block.TypeLabel()) - - if isDynamic { - if iterAttr := block.GetAttribute("iterator"); iterAttr.IsNotNil() { - refs := iterAttr.AllReferences() - if len(refs) == 1 { - ctx.Set(idx, refs[0].TypeLabel(), "key") - ctx.Set(val, refs[0].TypeLabel(), "value") - } else { - e.logger.Debug("Ignoring iterator attribute in dynamic block, expected one reference", - log.Int("refs", len(refs))) - } - } - } - forEachFiltered = append(forEachFiltered, clone) - clones[idx.AsString()] = clone.Values() }) diff --git a/pkg/iac/scanners/terraform/parser/parser_test.go b/pkg/iac/scanners/terraform/parser/parser_test.go index e3bd817748f6..540338afb57f 100644 --- a/pkg/iac/scanners/terraform/parser/parser_test.go +++ b/pkg/iac/scanners/terraform/parser/parser_test.go @@ -1367,139 +1367,284 @@ func TestCountMetaArgumentInModule(t *testing.T) { } func TestDynamicBlocks(t *testing.T) { - t.Run("arg is list of int", func(t *testing.T) { - modules := parse(t, map[string]string{ - "main.tf": ` -resource "aws_security_group" "sg-webserver" { - vpc_id = "1111" - dynamic "ingress" { + tests := []struct { + name string + src string + expected []any + }{ + { + name: "for-each use tuple of int", + src: `resource "test_resource" "test" { + dynamic "foo" { for_each = [80, 443] content { - from_port = ingress.value - to_port = ingress.value - protocol = "tcp" - cidr_blocks = ["0.0.0.0/0"] + bar = foo.value } } -} -`, - }) - require.Len(t, modules, 1) - - secGroups := modules.GetResourcesByType("aws_security_group") - assert.Len(t, secGroups, 1) - ingressBlocks := secGroups[0].GetBlocks("ingress") - assert.Len(t, ingressBlocks, 2) - - var inboundPorts []int - for _, ingress := range ingressBlocks { - fromPort := ingress.GetAttribute("from_port").AsIntValueOrDefault(-1, ingress).Value() - inboundPorts = append(inboundPorts, fromPort) - } - - assert.True(t, compareSets([]int{80, 443}, inboundPorts)) - }) - - t.Run("empty for-each", func(t *testing.T) { - modules := parse(t, map[string]string{ - "main.tf": ` -resource "aws_lambda_function" "analyzer" { - dynamic "vpc_config" { +}`, + expected: []any{float64(80), float64(443)}, + }, + { + name: "for-each use list of int", + src: `resource "test_resource" "test" { + dynamic "foo" { + for_each = tolist([80, 443]) + content { + bar = foo.value + } + } +}`, + expected: []any{float64(80), float64(443)}, + }, + { + name: "for-each use set of int", + src: `resource "test_resource" "test" { + dynamic "foo" { + for_each = toset([80, 443]) + content { + bar = foo.value + } + } +}`, + expected: []any{float64(80), float64(443)}, + }, + { + name: "for-each use list of bool", + src: `resource "test_resource" "test" { + dynamic "foo" { + for_each = tolist([true]) + content { + bar = foo.value + } + } +}`, + expected: []any{true}, + }, + { + name: "empty for-each", + src: `resource "test_resource" "test" { + dynamic "foo" { for_each = [] content {} } +}`, + expected: []any{}, + }, + { + name: "for-each use tuple of objects", + src: `variable "test_var" { + type = list(object({ enabled = bool })) + default = [{ enabled = true }] } -`, - }) - require.Len(t, modules, 1) - functions := modules.GetResourcesByType("aws_lambda_function") - assert.Len(t, functions, 1) - vpcConfigs := functions[0].GetBlocks("vpc_config") - assert.Empty(t, vpcConfigs) - }) +resource "test_resource" "test" { + dynamic "foo" { + for_each = var.test_var - t.Run("arg is list of bool", func(t *testing.T) { - modules := parse(t, map[string]string{ - "main.tf": ` -resource "aws_lambda_function" "analyzer" { - dynamic "vpc_config" { - for_each = [true] - content {} + content { + bar = foo.value.enabled + } + } +}`, + expected: []any{true}, + }, + { + name: "attribute ref to object key", + src: `variable "some_var" { + type = map( + object({ + tag = string + }) + ) + default = { + ssh = { "tag" = "login" } + http = { "tag" = "proxy" } + https = { "tag" = "proxy" } } } -`, - }) - require.Len(t, modules, 1) - - functions := modules.GetResourcesByType("aws_lambda_function") - assert.Len(t, functions, 1) - vpcConfigs := functions[0].GetBlocks("vpc_config") - assert.Len(t, vpcConfigs, 1) - }) - t.Run("arg is list of objects", func(t *testing.T) { - modules := parse(t, map[string]string{ - "main.tf": `locals { - cluster_network_policy = [{ - enabled = true - }] +resource "test_resource" "test" { + dynamic "foo" { + for_each = { for name, values in var.some_var : name => values } + content { + bar = foo.key + } + } +}`, + expected: []any{"ssh", "http", "https"}, + }, + { + name: "attribute ref to object value", + src: `variable "some_var" { + type = map( + object({ + tag = string + }) + ) + default = { + ssh = { "tag" = "login" } + http = { "tag" = "proxy" } + https = { "tag" = "proxy" } + } } -resource "google_container_cluster" "primary" { - name = "test" +resource "test_resource" "test" { + dynamic "foo" { + for_each = { for name, values in var.some_var : name => values } + content { + bar = foo.value.tag + } + } +}`, + expected: []any{"login", "proxy", "proxy"}, + }, + { + name: "attribute ref to map key", + src: `variable "some_var" { + type = map + default = { + ssh = { "tag" = "login" } + http = { "tag" = "proxy" } + https = { "tag" = "proxy" } + } +} - dynamic "network_policy" { - for_each = local.cluster_network_policy +resource "test_resource" "test" { + dynamic "foo" { + for_each = var.some_var + content { + bar = foo.key + } + } +}`, + expected: []any{"ssh", "http", "https"}, + }, + { + name: "attribute ref to map value", + src: `variable "some_var" { + type = map + default = { + ssh = { "tag" = "login" } + http = { "tag" = "proxy" } + https = { "tag" = "proxy" } + } +} +resource "test_resource" "test" { + dynamic "foo" { + for_each = var.some_var content { - enabled = network_policy.value.enabled + bar = foo.value.tag } } }`, - }) - require.Len(t, modules, 1) + expected: []any{"login", "proxy", "proxy"}, + }, + { + name: "dynamic block with iterator", + src: `resource "test_resource" "test" { + dynamic "foo" { + for_each = ["foo", "bar"] + iterator = some_iterator + content { + bar = some_iterator.value + } + } +}`, + expected: []any{"foo", "bar"}, + }, + { + name: "iterator and parent block with same name", + src: `resource "test_resource" "test" { + dynamic "foo" { + for_each = ["foo", "bar"] + iterator = foo + content { + bar = foo.value + } + } +}`, + expected: []any{"foo", "bar"}, + }, + { + name: "for-each use null value", + src: `resource "test_resource" "test" { + dynamic "foo" { + for_each = null + content { + bar = foo.value + } + } +}`, + expected: []any{}, + }, + { + name: "no for-each attribute", + src: `resource "test_resource" "test" { + dynamic "foo" { + content { + bar = foo.value + } + } +}`, + expected: []any{}, + }, + } - clusters := modules.GetResourcesByType("google_container_cluster") - assert.Len(t, clusters, 1) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + modules := parse(t, map[string]string{ + "main.tf": tt.src, + }) + require.Len(t, modules, 1) - networkPolicies := clusters[0].GetBlocks("network_policy") - assert.Len(t, networkPolicies, 1) + resource := modules.GetResourcesByType("test_resource") + require.Len(t, resource, 1) + blocks := resource[0].GetBlocks("foo") - enabled := networkPolicies[0].GetAttribute("enabled") - assert.True(t, enabled.Value().True()) - }) + var vals []any + for _, attr := range blocks { + vals = append(vals, attr.GetAttribute("bar").GetRawValue()) + } - t.Run("nested dynamic", func(t *testing.T) { - modules := parse(t, map[string]string{ - "main.tf": ` -resource "test_block" "this" { - name = "name" - location = "loc" - dynamic "env" { - for_each = ["1", "2"] - content { - dynamic "value_source" { - for_each = [true, true] - content {} - } + assert.ElementsMatch(t, tt.expected, vals) + }) } +} + +func TestNestedDynamicBlock(t *testing.T) { + modules := parse(t, map[string]string{ + "main.tf": `resource "test_resource" "test" { + dynamic "foo" { + for_each = ["1", "1"] + content { + dynamic "bar" { + for_each = [true, true] + content { + baz = foo.value + qux = bar.value + } + } + } } }`, - }) - require.Len(t, modules, 1) + }) + require.Len(t, modules, 1) - testResources := modules.GetResourcesByType("test_block") - assert.Len(t, testResources, 1) - envs := testResources[0].GetBlocks("env") - assert.Len(t, envs, 2) + testResources := modules.GetResourcesByType("test_resource") + assert.Len(t, testResources, 1) + blocks := testResources[0].GetBlocks("foo") + assert.Len(t, blocks, 2) - var sources []*terraform.Block - for _, env := range envs { - sources = append(sources, env.GetBlocks("value_source")...) + var nested []*terraform.Block + for _, block := range blocks { + nested = append(nested, block.GetBlocks("bar")...) + for _, b := range nested { + assert.Equal(t, "1", b.GetAttribute("baz").GetRawValue()) + assert.Equal(t, true, b.GetAttribute("qux").GetRawValue()) } - assert.Len(t, sources, 4) - }) + } + assert.Len(t, nested, 4) } func parse(t *testing.T, files map[string]string) terraform.Modules { @@ -1513,21 +1658,6 @@ func parse(t *testing.T, files map[string]string) terraform.Modules { return modules } -func compareSets(a, b []int) bool { - m := make(map[int]bool) - for _, el := range a { - m[el] = true - } - - for _, el := range b { - if !m[el] { - return false - } - } - - return true -} - func TestModuleRefersToOutputOfAnotherModule(t *testing.T) { files := map[string]string{ "main.tf": ` @@ -1775,42 +1905,6 @@ variable "foo" {} assert.Equal(t, "bar", blocks[0].GetAttribute("foo").Value().AsString()) } -func TestDynamicWithIterator(t *testing.T) { - fsys := fstest.MapFS{ - "main.tf": &fstest.MapFile{ - Data: []byte(`resource "aws_s3_bucket" "this" { - dynamic versioning { - for_each = [true] - iterator = ver - - content { - enabled = ver.value - } - } -}`), - }, - } - - parser := New( - fsys, "", - OptionStopOnHCLError(true), - OptionWithDownloads(false), - ) - require.NoError(t, parser.ParseFS(context.TODO(), ".")) - - modules, _, err := parser.EvaluateAll(context.TODO()) - require.NoError(t, err) - - assert.Len(t, modules, 1) - - buckets := modules.GetResourcesByType("aws_s3_bucket") - assert.Len(t, buckets, 1) - - attr, _ := buckets[0].GetNestedAttribute("versioning.enabled") - - assert.True(t, attr.Value().True()) -} - func Test_AWSRegionNameDefined(t *testing.T) { fs := testutil.CreateFS(t, map[string]string{ diff --git a/pkg/iac/terraform/attribute.go b/pkg/iac/terraform/attribute.go index 39161a72a379..9c5536357283 100644 --- a/pkg/iac/terraform/attribute.go +++ b/pkg/iac/terraform/attribute.go @@ -729,15 +729,16 @@ func (a *Attribute) IsTrue() bool { if a == nil { return false } - switch a.Value().Type() { + val := a.Value() + switch val.Type() { case cty.Bool: - return a.Value().True() + return val.True() case cty.String: - val := a.Value().AsString() + val := val.AsString() val = strings.Trim(val, "\"") return strings.EqualFold(val, "true") case cty.Number: - val := a.Value().AsBigFloat() + val := val.AsBigFloat() f, _ := val.Float64() return f > 0 } diff --git a/pkg/iac/terraform/block.go b/pkg/iac/terraform/block.go index dbf7352959d0..dd6d8446c124 100644 --- a/pkg/iac/terraform/block.go +++ b/pkg/iac/terraform/block.go @@ -1,6 +1,7 @@ package terraform import ( + "errors" "fmt" "io/fs" "strconv" @@ -137,16 +138,15 @@ func (b *Block) GetRawValue() any { return nil } -func (b *Block) InjectBlock(block *Block, name string) { - block.hclBlock.Labels = []string{} - block.hclBlock.Type = name +func (b *Block) injectBlock(block *Block) { for attrName, attr := range block.Attributes() { - b.context.Root().SetByDot(attr.Value(), fmt.Sprintf("%s.%s.%s", b.reference.String(), name, attrName)) + path := fmt.Sprintf("%s.%s.%s", b.reference.String(), block.hclBlock.Type, attrName) + b.context.Root().SetByDot(attr.Value(), path) } b.childBlocks = append(b.childBlocks, block) } -func (b *Block) MarkExpanded() { +func (b *Block) markExpanded() { b.expanded = true } @@ -154,17 +154,26 @@ func (b *Block) IsExpanded() bool { return b.expanded } -func (b *Block) Clone(index cty.Value) *Block { - var childCtx *context.Context - if b.context != nil { - childCtx = b.context.NewChild() - } else { - childCtx = context.NewContext(&hcl.EvalContext{}, nil) +func (b *Block) inherit(ctx *context.Context, index ...cty.Value) *Block { + return NewBlock(b.copyBlock(), ctx, b.moduleBlock, b.parentBlock, b.moduleSource, b.moduleFS, index...) +} + +func (b *Block) copyBlock() *hcl.Block { + hclBlock := *b.hclBlock + return &hclBlock +} + +func (b *Block) childContext() *context.Context { + if b.context == nil { + return context.NewContext(&hcl.EvalContext{}, nil) } + return b.context.NewChild() +} - cloneHCL := *b.hclBlock +func (b *Block) Clone(index cty.Value) *Block { + childCtx := b.childContext() + clone := b.inherit(childCtx, index) - clone := NewBlock(&cloneHCL, childCtx, b.moduleBlock, b.parentBlock, b.moduleSource, b.moduleFS, index) if len(clone.hclBlock.Labels) > 0 { position := len(clone.hclBlock.Labels) - 1 labels := make([]string, len(clone.hclBlock.Labels)) @@ -188,7 +197,7 @@ func (b *Block) Clone(index cty.Value) *Block { } indexVal, _ := gocty.ToCtyValue(index, cty.Number) clone.context.SetByDot(indexVal, "count.index") - clone.MarkExpanded() + clone.markExpanded() b.cloneIndex++ return clone } @@ -446,6 +455,17 @@ func (b *Block) LocalName() string { return b.reference.String() } +func (b *Block) FullLocalName() string { + if b.parentBlock != nil { + return fmt.Sprintf( + "%s.%s", + b.parentBlock.FullLocalName(), + b.LocalName(), + ) + } + return b.LocalName() +} + func (b *Block) FullName() string { if b.moduleBlock != nil { @@ -576,3 +596,118 @@ func (b *Block) IsNil() bool { func (b *Block) IsNotNil() bool { return !b.IsNil() } + +func (b *Block) ExpandBlock() error { + var ( + expanded []*Block + errs []error + ) + + for _, child := range b.childBlocks { + if child.Type() == "dynamic" { + blocks, err := child.expandDynamic() + if err != nil { + errs = append(errs, err) + continue + } + expanded = append(expanded, blocks...) + } + } + + for _, block := range expanded { + b.injectBlock(block) + } + + return errors.Join(errs...) +} + +func (b *Block) expandDynamic() ([]*Block, error) { + if b.IsExpanded() || b.Type() != "dynamic" { + return nil, nil + } + + realBlockType := b.TypeLabel() + if realBlockType == "" { + return nil, errors.New("dynamic block must have 1 label") + } + + forEachVal, err := b.validateForEach() + if err != nil { + return nil, fmt.Errorf("invalid for-each in %s block: %w", b.FullLocalName(), err) + } + + var ( + expanded []*Block + errs []error + ) + + forEachVal.ForEachElement(func(key, val cty.Value) (stop bool) { + if val.IsNull() { + return + } + + iteratorName, err := b.iteratorName(realBlockType) + if err != nil { + errs = append(errs, err) + return + } + + forEachCtx := b.childContext() + obj := cty.ObjectVal(map[string]cty.Value{ + "key": key, + "value": val, + }) + forEachCtx.Set(obj, iteratorName) + + if content := b.GetBlock("content"); content != nil { + inherited := content.inherit(forEachCtx) + inherited.hclBlock.Labels = []string{} + inherited.hclBlock.Type = realBlockType + if err := inherited.ExpandBlock(); err != nil { + errs = append(errs, err) + return + } + expanded = append(expanded, inherited) + } + return + }) + + if len(expanded) > 0 { + b.markExpanded() + } + + return expanded, errors.Join(errs...) +} + +func (b *Block) validateForEach() (cty.Value, error) { + forEachAttr := b.GetAttribute("for_each") + if forEachAttr == nil { + return cty.NilVal, errors.New("for_each attribute required") + } + + forEachVal := forEachAttr.Value() + + if !forEachVal.CanIterateElements() { + return cty.NilVal, fmt.Errorf("cannot use a %s value in for_each. An iterable collection is required", forEachVal.GoString()) + } + + return forEachVal, nil +} + +func (b *Block) iteratorName(blockType string) (string, error) { + iteratorAttr := b.GetAttribute("iterator") + if iteratorAttr == nil { + return blockType, nil + } + + traversal, diags := hcl.AbsTraversalForExpr(iteratorAttr.hclAttribute.Expr) + if diags.HasErrors() { + return "", diags + } + + if len(traversal) != 1 { + return "", fmt.Errorf("dynamic iterator must be a single variable name") + } + + return traversal.RootName(), nil +} From 57e24aa85382f749df7f673e241caaf3fcbb45cb Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Mon, 21 Oct 2024 11:06:50 +0200 Subject: [PATCH 60/94] fix: enable usestdlibvars linter (#7770) Signed-off-by: Matthieu MOREL --- .golangci.yaml | 1 + integration/registry_test.go | 2 +- pkg/dependency/parser/java/pom/parse.go | 2 +- pkg/iac/adapters/terraform/aws/apigateway/adapt_test.go | 3 ++- pkg/iac/adapters/terraform/aws/apigateway/apiv1_test.go | 5 +++-- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 95c66cc69f73..40bfa36e1a64 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -105,6 +105,7 @@ linters: - typecheck - unconvert - unused + - usestdlibvars run: go: '1.22' diff --git a/integration/registry_test.go b/integration/registry_test.go index aded09adce35..25ddaf5b2814 100644 --- a/integration/registry_test.go +++ b/integration/registry_test.go @@ -334,7 +334,7 @@ func requestRegistryToken(imageRef name.Reference, baseDir string, opt registryO } // Get a registry token - req, err := http.NewRequest("GET", fmt.Sprintf("%s/auth", opt.AuthURL), nil) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/auth", opt.AuthURL), nil) if err != nil { return "", err } diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go index 2c8a194ea50b..60a83ba9d81b 100644 --- a/pkg/dependency/parser/java/pom/parse.go +++ b/pkg/dependency/parser/java/pom/parse.go @@ -703,7 +703,7 @@ func (p *Parser) remoteRepoRequest(repo string, paths []string) (*http.Request, paths = append([]string{repoURL.Path}, paths...) repoURL.Path = path.Join(paths...) - req, err := http.NewRequest("GET", repoURL.String(), http.NoBody) + req, err := http.NewRequest(http.MethodGet, repoURL.String(), http.NoBody) if err != nil { return nil, xerrors.Errorf("unable to create HTTP request: %w", err) } diff --git a/pkg/iac/adapters/terraform/aws/apigateway/adapt_test.go b/pkg/iac/adapters/terraform/aws/apigateway/adapt_test.go index 65393ae82f82..8d2b0155fee5 100644 --- a/pkg/iac/adapters/terraform/aws/apigateway/adapt_test.go +++ b/pkg/iac/adapters/terraform/aws/apigateway/adapt_test.go @@ -1,6 +1,7 @@ package apigateway import ( + "net/http" "testing" "github.com/stretchr/testify/assert" @@ -72,7 +73,7 @@ resource "aws_apigatewayv2_domain_name" "example" { { Methods: []v1.Method{ { - HTTPMethod: String("GET"), + HTTPMethod: String(http.MethodGet), AuthorizationType: String("NONE"), APIKeyRequired: Bool(false), }, diff --git a/pkg/iac/adapters/terraform/aws/apigateway/apiv1_test.go b/pkg/iac/adapters/terraform/aws/apigateway/apiv1_test.go index cf69e8d0ee23..9932ac864e7b 100644 --- a/pkg/iac/adapters/terraform/aws/apigateway/apiv1_test.go +++ b/pkg/iac/adapters/terraform/aws/apigateway/apiv1_test.go @@ -1,6 +1,7 @@ package apigateway import ( + "net/http" "testing" "github.com/aquasecurity/trivy/internal/testutil" @@ -35,7 +36,7 @@ resource "aws_api_gateway_method" "example" { `, expected: []v1.Method{ { - HTTPMethod: String("GET"), + HTTPMethod: String(http.MethodGet), AuthorizationType: String("NONE"), APIKeyRequired: Bool(false), }, @@ -63,7 +64,7 @@ resource "aws_api_gateway_method" "example" { `, expected: []v1.Method{ { - HTTPMethod: String("GET"), + HTTPMethod: String(http.MethodGet), AuthorizationType: String("NONE"), APIKeyRequired: Bool(true), }, From f6acdf713991f8ffdbe765178fcb8a9cde433cba Mon Sep 17 00:00:00 2001 From: Pierre Baumard Date: Mon, 21 Oct 2024 11:38:35 +0200 Subject: [PATCH 61/94] fix(license): fix license normalization for Universal Permissive License (#7766) --- pkg/licensing/normalize.go | 2 +- pkg/licensing/normalize_test.go | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/licensing/normalize.go b/pkg/licensing/normalize.go index 4ce294275214..bce81e68903d 100644 --- a/pkg/licensing/normalize.go +++ b/pkg/licensing/normalize.go @@ -626,7 +626,7 @@ func TrimLicenseText(text string) string { } // version number match -var versionRegexpString = "([A-UW-Z)]{2,})( LICENSE)?\\s*[,(-]?\\s*(V|V\\.|VER|VER\\.|VERSION|VERSION-|-)?\\s*([1-9](\\.\\d)*)[)]?" +var versionRegexpString = "([A-UW-Z)])( LICENSE)?\\s*[,(-]?\\s*(V|V\\.|VER|VER\\.|VERSION|VERSION-|-)?\\s*([1-9](\\.\\d)*)[)]?" // case insensitive version match anywhere in string var versionRegexp = regexp.MustCompile("(?i)" + versionRegexpString) diff --git a/pkg/licensing/normalize_test.go b/pkg/licensing/normalize_test.go index 9b47fd923f29..7daf7b57d783 100644 --- a/pkg/licensing/normalize_test.go +++ b/pkg/licensing/normalize_test.go @@ -209,6 +209,13 @@ func TestNormalize(t *testing.T) { normalized: " The unmapped license ", normalizedKey: " The unmapped license ", }, + { + licenses: []string{ + "Universal Permissive License, Version 1.0", + }, + normalized: "UPL-1.0", + normalizedKey: "UPL-1.0", + }, } for _, tt := range tests { t.Run(tt.normalized, func(t *testing.T) { From 010b2138067184114a882d3b5d86e2f556f4355c Mon Sep 17 00:00:00 2001 From: afdesk Date: Tue, 22 Oct 2024 00:25:54 +0600 Subject: [PATCH 62/94] refactor(k8s): scan config files as a folder (#7690) --- pkg/k8s/scanner/io.go | 50 ++++++++++++++++++----- pkg/k8s/scanner/io_test.go | 5 +++ pkg/k8s/scanner/scanner.go | 82 ++++++++++++++++++++++---------------- 3 files changed, 92 insertions(+), 45 deletions(-) diff --git a/pkg/k8s/scanner/io.go b/pkg/k8s/scanner/io.go index 9c32699ddd63..65f102a4b08c 100644 --- a/pkg/k8s/scanner/io.go +++ b/pkg/k8s/scanner/io.go @@ -3,6 +3,7 @@ package scanner import ( "fmt" "os" + "path/filepath" "regexp" "runtime" @@ -13,36 +14,63 @@ import ( "github.com/aquasecurity/trivy/pkg/log" ) -var r = regexp.MustCompile("\\\\|/|:|\\*|\\?|<|>") +var r = regexp.MustCompile("[\\\\/:*?<>]") -func createTempFile(artifact *artifacts.Artifact) (string, error) { +func generateTempFileByArtifact(artifact *artifacts.Artifact, tempDir string) (string, error) { filename := fmt.Sprintf("%s-%s-%s-*.yaml", artifact.Namespace, artifact.Kind, artifact.Name) - if runtime.GOOS == "windows" { // removes characters not permitted in file/directory names on Windows filename = filenameWindowsFriendly(filename) } - file, err := os.CreateTemp("", filename) + file, err := os.CreateTemp(tempDir, filename) if err != nil { - return "", xerrors.Errorf("creating tmp file error: %w", err) + return "", xerrors.Errorf("failed to create temporary file: %w", err) } + shouldRemove := false defer func() { if err := file.Close(); err != nil { - log.Error("Failed to close temp file", log.String("path", file.Name()), log.Err(err)) + log.Error("Failed to close temp file", log.FilePath(file.Name()), log.Err(err)) + } + if shouldRemove { + removeFile(file.Name()) } }() - if err := yaml.NewEncoder(file).Encode(artifact.RawResource); err != nil { - removeFile(filename) - return "", xerrors.Errorf("marshaling resource error: %w", err) + shouldRemove = true + return "", xerrors.Errorf("failed to encode artifact: %w", err) + } + return filepath.Base(file.Name()), nil +} + +// generateTempDir creates a directory with yaml files generated from kubernetes artifacts +// returns a directory name, a map for mapping a temp target file to k8s artifact and error +func generateTempDir(arts []*artifacts.Artifact) (string, map[string]*artifacts.Artifact, error) { + tempDir, err := os.MkdirTemp("", "trivyk8s*") + if err != nil { + return "", nil, xerrors.Errorf("failed to create temp directory: %w", err) + } + + m := make(map[string]*artifacts.Artifact) + for _, artifact := range arts { + filename, err := generateTempFileByArtifact(artifact, tempDir) + if err != nil { + log.Error("Failed to create temp file", log.FilePath(filename), log.Err(err)) + continue + } + m[filename] = artifact } + return tempDir, m, nil +} - return file.Name(), nil +func removeDir(dirname string) { + if err := os.RemoveAll(dirname); err != nil { + log.Error("Failed to remove temp directory", log.FilePath(dirname), log.Err(err)) + } } func removeFile(filename string) { if err := os.Remove(filename); err != nil { - log.Error("Failed to remove temp file", log.String("path", filename), log.Err(err)) + log.Error("Failed to remove temp file", log.FilePath(filename), log.Err(err)) } } diff --git a/pkg/k8s/scanner/io_test.go b/pkg/k8s/scanner/io_test.go index 7587d1bb8282..9e256b39f2b3 100644 --- a/pkg/k8s/scanner/io_test.go +++ b/pkg/k8s/scanner/io_test.go @@ -23,6 +23,11 @@ func Test_FilenameWindowsFriendly(t *testing.T) { fileName: `kube-system-Role-system-controller-bootstrap-signer-2934213283.yaml`, want: `kube-system-Role-system-controller-bootstrap-signer-2934213283.yaml`, }, + { + name: "name with no invalid - slash", + fileName: "-ClusterRoleBinding-system\\basic-user-725844313.yaml", + want: `-ClusterRoleBinding-system_basic-user-725844313.yaml`, + }, } for _, test := range tests { diff --git a/pkg/k8s/scanner/scanner.go b/pkg/k8s/scanner/scanner.go index 67d06b4c54bd..70debfe6a85f 100644 --- a/pkg/k8s/scanner/scanner.go +++ b/pkg/k8s/scanner/scanner.go @@ -82,14 +82,18 @@ func (s *Scanner) Scan(ctx context.Context, artifactsData []*artifacts.Artifact) var resources []report.Resource - type scanResult struct { - vulns []report.Resource - misconfig report.Resource + // scans kubernetes artifacts as a scope of yaml files + if local.ShouldScanMisconfigOrRbac(s.opts.Scanners) { + misconfigs, err := s.scanMisconfigs(ctx, resourceArtifacts) + if err != nil { + return report.Report{}, xerrors.Errorf("scanning misconfigurations error: %w", err) + } + resources = append(resources, misconfigs...) } - onItem := func(ctx context.Context, artifact *artifacts.Artifact) (scanResult, error) { - scanResults := scanResult{} - if s.opts.Scanners.AnyEnabled(types.VulnerabilityScanner, types.SecretScanner) && !s.opts.SkipImages { + // scan images from kubernetes cluster in parallel + if s.opts.Scanners.AnyEnabled(types.VulnerabilityScanner, types.SecretScanner) && !s.opts.SkipImages { + onItem := func(ctx context.Context, artifact *artifacts.Artifact) ([]report.Resource, error) { opts := s.opts opts.Credentials = make([]ftypes.Credential, len(s.opts.Credentials)) copy(opts.Credentials, s.opts.Credentials) @@ -106,33 +110,22 @@ func (s *Scanner) Scan(ctx context.Context, artifactsData []*artifacts.Artifact) } vulns, err := s.scanVulns(ctx, artifact, opts) if err != nil { - return scanResult{}, xerrors.Errorf("scanning vulnerabilities error: %w", err) + return nil, xerrors.Errorf("scanning vulnerabilities error: %w", err) } - scanResults.vulns = vulns + return vulns, nil } - if local.ShouldScanMisconfigOrRbac(s.opts.Scanners) { - misconfig, err := s.scanMisconfigs(ctx, artifact) - if err != nil { - return scanResult{}, xerrors.Errorf("scanning misconfigurations error: %w", err) - } - scanResults.misconfig = misconfig + + onResult := func(result []report.Resource) error { + resources = append(resources, result...) + return nil } - return scanResults, nil - } - onResult := func(result scanResult) error { - resources = append(resources, result.vulns...) - // don't add empty misconfig results to resources slice to avoid an empty resource - if result.misconfig.Results != nil { - resources = append(resources, result.misconfig) + p := parallel.NewPipeline(s.opts.Parallel, !s.opts.Quiet, resourceArtifacts, onItem, onResult) + if err := p.Do(ctx); err != nil { + return report.Report{}, err } - return nil } - p := parallel.NewPipeline(s.opts.Parallel, !s.opts.Quiet, resourceArtifacts, onItem, onResult) - if err := p.Do(ctx); err != nil { - return report.Report{}, err - } if s.opts.Scanners.AnyEnabled(types.VulnerabilityScanner) { k8sResource, err := s.scanK8sVulns(ctx, k8sCoreArtifacts) if err != nil { @@ -173,22 +166,43 @@ func (s *Scanner) scanVulns(ctx context.Context, artifact *artifacts.Artifact, o return resources, nil } -func (s *Scanner) scanMisconfigs(ctx context.Context, artifact *artifacts.Artifact) (report.Resource, error) { - configFile, err := createTempFile(artifact) +func (s *Scanner) scanMisconfigs(ctx context.Context, k8sArtifacts []*artifacts.Artifact) ([]report.Resource, error) { + dir, artifactsByFilename, err := generateTempDir(k8sArtifacts) if err != nil { - return report.Resource{}, xerrors.Errorf("scan error: %w", err) + return nil, xerrors.Errorf("failed to generate temp dir: %w", err) } - s.opts.Target = configFile + s.opts.Target = dir configReport, err := s.runner.ScanFilesystem(ctx, s.opts) - // remove config file after scanning - removeFile(configFile) + // remove config files after scanning + removeDir(dir) + if err != nil { - return report.CreateResource(artifact, configReport, err), err + return nil, xerrors.Errorf("failed to scan filesystem: %w", err) + } + resources := make([]report.Resource, 0, len(k8sArtifacts)) + + for _, res := range configReport.Results { + artifact := artifactsByFilename[res.Target] + + singleReport := types.Report{ + SchemaVersion: configReport.SchemaVersion, + CreatedAt: configReport.CreatedAt, + ArtifactName: res.Target, + ArtifactType: configReport.ArtifactType, + Metadata: configReport.Metadata, + Results: types.Results{res}, + } + + resource, err := s.filter(ctx, singleReport, artifact) + if err != nil { + resource = report.CreateResource(artifact, singleReport, err) + } + resources = append(resources, resource) } - return s.filter(ctx, configReport, artifact) + return resources, nil } func (s *Scanner) filter(ctx context.Context, r types.Report, artifact *artifacts.Artifact) (report.Resource, error) { var err error From 9514148767865baddd73a49245385574927f7a74 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Tue, 22 Oct 2024 02:55:12 +0600 Subject: [PATCH 63/94] feat(misconf): export unresolvable field of IaC types to Rego (#7765) Signed-off-by: nikpivkin --- pkg/iac/rego/convert/slice_test.go | 2 ++ pkg/iac/rego/schemas/cloud.json | 21 +++++++++++++++++++++ pkg/iac/state/state_test.go | 2 ++ pkg/iac/types/metadata.go | 1 + pkg/iac/types/metadata_test.go | 3 +++ 5 files changed, 29 insertions(+) diff --git a/pkg/iac/rego/convert/slice_test.go b/pkg/iac/rego/convert/slice_test.go index e30c200142b2..ff318e2b1a03 100644 --- a/pkg/iac/rego/convert/slice_test.go +++ b/pkg/iac/rego/convert/slice_test.go @@ -38,6 +38,7 @@ func Test_SliceTypesConversion(t *testing.T) { "endline": 123, "sourceprefix": "", "managed": true, + "unresolvable": false, "explicit": false, "fskey": "", "resource": "", @@ -49,6 +50,7 @@ func Test_SliceTypesConversion(t *testing.T) { "endline": 123, "sourceprefix": "", "managed": true, + "unresolvable": false, "explicit": false, "fskey": "", "resource": "", diff --git a/pkg/iac/rego/schemas/cloud.json b/pkg/iac/rego/schemas/cloud.json index 3cc6301429be..bdaad1330898 100644 --- a/pkg/iac/rego/schemas/cloud.json +++ b/pkg/iac/rego/schemas/cloud.json @@ -7884,6 +7884,9 @@ "startline": { "type": "integer" }, + "unresolvable": { + "type": "boolean" + }, "value": { "type": "boolean" } @@ -7916,6 +7919,9 @@ "startline": { "type": "integer" }, + "unresolvable": { + "type": "boolean" + }, "value": { "type": "string" } @@ -7948,6 +7954,9 @@ "startline": { "type": "integer" }, + "unresolvable": { + "type": "boolean" + }, "value": { "type": "integer" } @@ -7980,6 +7989,9 @@ "startline": { "type": "integer" }, + "unresolvable": { + "type": "boolean" + }, "value": { "type": "object" } @@ -8011,6 +8023,9 @@ }, "startline": { "type": "integer" + }, + "unresolvable": { + "type": "boolean" } } }, @@ -8041,6 +8056,9 @@ "startline": { "type": "integer" }, + "unresolvable": { + "type": "boolean" + }, "value": { "type": "string" } @@ -8073,6 +8091,9 @@ "startline": { "type": "integer" }, + "unresolvable": { + "type": "boolean" + }, "value": { "type": "string" } diff --git a/pkg/iac/state/state_test.go b/pkg/iac/state/state_test.go index 60b4b061a2d3..46de9b506d4b 100644 --- a/pkg/iac/state/state_test.go +++ b/pkg/iac/state/state_test.go @@ -44,6 +44,7 @@ func Test_RegoConversion(t *testing.T) { "startline": 2, "endline": 4, "managed": true, + "unresolvable": false, "explicit": false, "fskey": "", }, @@ -55,6 +56,7 @@ func Test_RegoConversion(t *testing.T) { "endline": 3, "value": "my-bucket", "managed": true, + "unresolvable": false, "explicit": false, "fskey": "", }, diff --git a/pkg/iac/types/metadata.go b/pkg/iac/types/metadata.go index 359654bdc43b..c71460441622 100755 --- a/pkg/iac/types/metadata.go +++ b/pkg/iac/types/metadata.go @@ -84,6 +84,7 @@ func (m *Metadata) ToRego() any { "sourceprefix": m.Range().GetSourcePrefix(), "managed": m.isManaged, "explicit": m.isExplicit, + "unresolvable": m.isUnresolvable, "fskey": CreateFSKey(m.Range().GetFS()), "resource": m.Reference(), } diff --git a/pkg/iac/types/metadata_test.go b/pkg/iac/types/metadata_test.go index f447c6d85ca2..f7d46bbf9dbd 100644 --- a/pkg/iac/types/metadata_test.go +++ b/pkg/iac/types/metadata_test.go @@ -8,12 +8,14 @@ import ( func Test_MetadataToRego(t *testing.T) { m1 := NewTestMetadata() + m1.isUnresolvable = true expected := map[string]any{ "endline": 123, "explicit": false, "filepath": "test.test", "fskey": "", "managed": true, + "unresolvable": true, "resource": "", "sourceprefix": "", "startline": 123, @@ -27,6 +29,7 @@ func Test_MetadataToRego(t *testing.T) { "filepath": "test.test", "fskey": "", "managed": true, + "unresolvable": false, "resource": "", "sourceprefix": "", "startline": 123, From f75c0d1f0069d4856cb4826d6049f32c5b9409d9 Mon Sep 17 00:00:00 2001 From: simar7 <1254783+simar7@users.noreply.github.com> Date: Wed, 23 Oct 2024 12:54:29 -0600 Subject: [PATCH 64/94] feat(misconf): Show misconfig ID in output (#7762) --- pkg/report/table/misconfig.go | 12 ++++++------ pkg/report/table/misconfig_test.go | 21 +++++++++++---------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/pkg/report/table/misconfig.go b/pkg/report/table/misconfig.go index 112d783d0875..dfb724bdf458 100644 --- a/pkg/report/table/misconfig.go +++ b/pkg/report/table/misconfig.go @@ -124,18 +124,18 @@ func (r *misconfigRenderer) renderSummary(misconf types.DetectedMisconfiguration } } - // severity + // ID & severity switch misconf.Severity { case severityCritical: - r.printf("%s: ", misconf.Severity) + r.printf("%s (%s): ", misconf.AVDID, misconf.Severity) case severityHigh: - r.printf("%s: ", misconf.Severity) + r.printf("%s (%s): ", misconf.AVDID, misconf.Severity) case severityMedium: - r.printf("%s: ", misconf.Severity) + r.printf("%s (%s): ", misconf.AVDID, misconf.Severity) case severityLow: - r.printf("%s: ", misconf.Severity) + r.printf("%s (%s): ", misconf.AVDID, misconf.Severity) default: - r.printf("%s: ", misconf.Severity) + r.printf("%s (%s): ", misconf.AVDID, misconf.Severity) } // heading diff --git a/pkg/report/table/misconfig_test.go b/pkg/report/table/misconfig_test.go index a57399f0e253..785b2621b504 100644 --- a/pkg/report/table/misconfig_test.go +++ b/pkg/report/table/misconfig_test.go @@ -27,7 +27,8 @@ func TestMisconfigRenderer(t *testing.T) { MisconfSummary: &types.MisconfSummary{Successes: 0, Failures: 1, Exceptions: 0}, Misconfigurations: []types.DetectedMisconfiguration{ { - ID: "AVD-XYZ-0123", + ID: "some-alias-for-a-check", + AVDID: "AVD-XYZ-0123", Title: "Config file is bad", Description: "Your config file is not good.", Message: "Oh no, a bad config.", @@ -44,7 +45,7 @@ my-file () Tests: 1 (SUCCESSES: 0, FAILURES: 1, EXCEPTIONS: 0) Failures: 1 (LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 0) -HIGH: Oh no, a bad config. +AVD-XYZ-0123 (HIGH): Oh no, a bad config. ════════════════════════════════════════ Your config file is not good. @@ -61,7 +62,7 @@ See https://google.com/search?q=bad%20config MisconfSummary: &types.MisconfSummary{Successes: 0, Failures: 1, Exceptions: 0}, Misconfigurations: []types.DetectedMisconfiguration{ { - ID: "AVD-XYZ-0123", + AVDID: "AVD-XYZ-0123", Title: "Config file is bad", Description: "Your config file is not good.", Message: "Oh no, a bad config.", @@ -103,7 +104,7 @@ my-file () Tests: 1 (SUCCESSES: 0, FAILURES: 1, EXCEPTIONS: 0) Failures: 1 (LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 0) -HIGH: Oh no, a bad config. +AVD-XYZ-0123 (HIGH): Oh no, a bad config. ════════════════════════════════════════ Your config file is not good. @@ -126,7 +127,7 @@ See https://google.com/search?q=bad%20config MisconfSummary: &types.MisconfSummary{Successes: 1, Failures: 1, Exceptions: 0}, Misconfigurations: []types.DetectedMisconfiguration{ { - ID: "AVD-XYZ-0123", + AVDID: "AVD-XYZ-0123", Title: "Config file is bad", Description: "Your config file is not good.", Message: "Oh no, a bad config.", @@ -157,7 +158,7 @@ See https://google.com/search?q=bad%20config }, }, { - ID: "AVD-XYZ-0456", + AVDID: "AVD-XYZ-0456", Title: "Config file is bad again", Description: "Your config file is still not good.", Message: "Oh no, a bad config AGAIN.", @@ -174,7 +175,7 @@ my-file () Tests: 2 (SUCCESSES: 1, FAILURES: 1, EXCEPTIONS: 0) Failures: 1 (LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 0) -FAIL: HIGH: Oh no, a bad config. +FAIL: AVD-XYZ-0123 (HIGH): Oh no, a bad config. ════════════════════════════════════════ Your config file is not good. @@ -188,7 +189,7 @@ See https://google.com/search?q=bad%20config ──────────────────────────────────────── -PASS: MEDIUM: Oh no, a bad config AGAIN. +PASS: AVD-XYZ-0456 (MEDIUM): Oh no, a bad config AGAIN. ════════════════════════════════════════ Your config file is still not good. @@ -213,7 +214,7 @@ See https://google.com/search?q=bad%20config { Type: "Terraform Security Check", ID: "AVD-AWS-0107", - AVDID: "AVS-AWS-0107", + AVDID: "AVD-AWS-0107", Title: "An ingress security group rule allows traffic from /0", Description: "Opening up ports to the public internet is generally to be avoided. You should restrict access to IP addresses or ranges that explicitly require it where possible.", Message: "Security group rule allows ingress from public internet.", @@ -312,7 +313,7 @@ terraform-aws-modules/security-group/aws/main.tf (terraform) Tests: 6 (SUCCESSES: 5, FAILURES: 1, EXCEPTIONS: 0) Failures: 1 (LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 1) -CRITICAL: Security group rule allows ingress from public internet. +AVD-AWS-0107 (CRITICAL): Security group rule allows ingress from public internet. ════════════════════════════════════════ Opening up ports to the public internet is generally to be avoided. You should restrict access to IP addresses or ranges that explicitly require it where possible. From c0d79fa09e645f3a3dbff878e393b8631fb17b64 Mon Sep 17 00:00:00 2001 From: Aaron Goldenthal Date: Thu, 24 Oct 2024 02:24:02 -0500 Subject: [PATCH 65/94] feat(report): update gitlab template to populate operating_system value (#7735) --- contrib/gitlab.tpl | 13 +- integration/client_server_test.go | 11 + integration/testdata/alpine-310.gitlab.golden | 8 +- integration/testdata/npm.gitlab.golden | 214 ++++++++++++++++++ 4 files changed, 239 insertions(+), 7 deletions(-) create mode 100644 integration/testdata/npm.gitlab.golden diff --git a/contrib/gitlab.tpl b/contrib/gitlab.tpl index 744c0c9394cb..7ff8abd8bfec 100644 --- a/contrib/gitlab.tpl +++ b/contrib/gitlab.tpl @@ -24,11 +24,18 @@ "status": "success", "type": "container_scanning" }, + {{- $image := "Unknown" -}} + {{- $os := "Unknown" -}} + {{- range . }} + {{- if eq .Class "os-pkgs" -}} + {{- $target := .Target }} + {{- $image = $target | regexFind "[^\\s]+" }} + {{- $os = $target | splitList "(" | last | trimSuffix ")" }} + {{- end }} + {{- end }} "vulnerabilities": [ {{- $t_first := true }} {{- range . }} - {{- $target := .Target }} - {{- $image := $target | regexFind "[^\\s]+" }} {{- range .Vulnerabilities -}} {{- if $t_first -}} {{- $t_first = false -}} @@ -65,7 +72,7 @@ "version": "{{ .InstalledVersion }}" }, {{- /* TODO: No mapping available - https://github.com/aquasecurity/trivy/issues/332 */}} - "operating_system": "Unknown", + "operating_system": "{{ $os }}", "image": "{{ $image }}" }, "identifiers": [ diff --git a/integration/client_server_test.go b/integration/client_server_test.go index 07a4f086200c..4afed3fdc155 100644 --- a/integration/client_server_test.go +++ b/integration/client_server_test.go @@ -323,6 +323,17 @@ func TestClientServerWithFormat(t *testing.T) { }, golden: "testdata/alpine-310.gitlab.golden", }, + { + name: "scan package-lock.json with gitlab template (Unknown os and image)", + args: csArgs{ + Command: "fs", + Format: "template", + TemplatePath: "@../contrib/gitlab.tpl", + Target: "testdata/fixtures/repo/npm/", + ListAllPackages: true, + }, + golden: "testdata/npm.gitlab.golden", + }, { name: "alpine 3.10 with gitlab-codequality template", args: csArgs{ diff --git a/integration/testdata/alpine-310.gitlab.golden b/integration/testdata/alpine-310.gitlab.golden index ad769b31959e..a0339dcf6bfb 100644 --- a/integration/testdata/alpine-310.gitlab.golden +++ b/integration/testdata/alpine-310.gitlab.golden @@ -37,7 +37,7 @@ }, "version": "1.1.1c-r0" }, - "operating_system": "Unknown", + "operating_system": "alpine 3.10.2", "image": "testdata/fixtures/images/alpine-310.tar.gz" }, "identifiers": [ @@ -104,7 +104,7 @@ }, "version": "1.1.1c-r0" }, - "operating_system": "Unknown", + "operating_system": "alpine 3.10.2", "image": "testdata/fixtures/images/alpine-310.tar.gz" }, "identifiers": [ @@ -191,7 +191,7 @@ }, "version": "1.1.1c-r0" }, - "operating_system": "Unknown", + "operating_system": "alpine 3.10.2", "image": "testdata/fixtures/images/alpine-310.tar.gz" }, "identifiers": [ @@ -258,7 +258,7 @@ }, "version": "1.1.1c-r0" }, - "operating_system": "Unknown", + "operating_system": "alpine 3.10.2", "image": "testdata/fixtures/images/alpine-310.tar.gz" }, "identifiers": [ diff --git a/integration/testdata/npm.gitlab.golden b/integration/testdata/npm.gitlab.golden new file mode 100644 index 000000000000..6c8cc2ce97ba --- /dev/null +++ b/integration/testdata/npm.gitlab.golden @@ -0,0 +1,214 @@ +{ + "version": "15.0.7", + "scan": { + "analyzer": { + "id": "trivy", + "name": "Trivy", + "vendor": { + "name": "Aqua Security" + }, + "version": "dev" + }, + "end_time": "2021-08-25T12:20:30", + "scanner": { + "id": "trivy", + "name": "Trivy", + "url": "https://github.com/aquasecurity/trivy/", + "vendor": { + "name": "Aqua Security" + }, + "version": "dev" + }, + "start_time": "2021-08-25T12:20:30", + "status": "success", + "type": "container_scanning" + }, + "vulnerabilities": [ + { + "id": "CVE-2019-11358", + "name": "jquery: Prototype pollution in object's prototype leading to denial of service, remote code execution, or property injection", + "description": "jQuery before 3.4.0, as used in Drupal, Backdrop CMS, and other products, mishandles jQuery.extend(true, {}, ...) because of Object.prototype pollution. If an unsanitized source object contained an enumerable __proto__ property, it could extend the native Object.prototype.", + "severity": "Medium", + "solution": "Upgrade jquery to 3.4.0", + "location": { + "dependency": { + "package": { + "name": "jquery" + }, + "version": "3.3.9" + }, + "operating_system": "Unknown", + "image": "Unknown" + }, + "identifiers": [ + { + "type": "cve", + "name": "CVE-2019-11358", + "value": "CVE-2019-11358", + "url": "https://avd.aquasec.com/nvd/cve-2019-11358" + } + ], + "links": [{ + "url": "http://lists.opensuse.org/opensuse-security-announce/2019-08/msg00006.html" + },{ + "url": "http://lists.opensuse.org/opensuse-security-announce/2019-08/msg00025.html" + },{ + "url": "http://packetstormsecurity.com/files/152787/dotCMS-5.1.1-Vulnerable-Dependencies.html" + },{ + "url": "http://packetstormsecurity.com/files/153237/RetireJS-CORS-Issue-Script-Execution.html" + },{ + "url": "http://packetstormsecurity.com/files/156743/OctoberCMS-Insecure-Dependencies.html" + },{ + "url": "http://seclists.org/fulldisclosure/2019/May/10" + },{ + "url": "http://seclists.org/fulldisclosure/2019/May/11" + },{ + "url": "http://seclists.org/fulldisclosure/2019/May/13" + },{ + "url": "http://www.openwall.com/lists/oss-security/2019/06/03/2" + },{ + "url": "http://www.securityfocus.com/bid/108023" + },{ + "url": "https://access.redhat.com/errata/RHBA-2019:1570" + },{ + "url": "https://access.redhat.com/errata/RHSA-2019:1456" + },{ + "url": "https://access.redhat.com/errata/RHSA-2019:2587" + },{ + "url": "https://access.redhat.com/errata/RHSA-2019:3023" + },{ + "url": "https://access.redhat.com/errata/RHSA-2019:3024" + },{ + "url": "https://access.redhat.com/security/cve/CVE-2019-11358" + },{ + "url": "https://backdropcms.org/security/backdrop-sa-core-2019-009" + },{ + "url": "https://blog.jquery.com/2019/04/10/jquery-3-4-0-released/" + },{ + "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11358" + },{ + "url": "https://github.com/DanielRuf/snyk-js-jquery-174006?files=1" + },{ + "url": "https://github.com/advisories/GHSA-6c3j-c64m-qhgq" + },{ + "url": "https://github.com/jquery/jquery/commit/753d591aea698e57d6db58c9f722cd0808619b1b" + },{ + "url": "https://github.com/jquery/jquery/pull/4333" + },{ + "url": "https://github.com/rails/jquery-rails/blob/master/CHANGELOG.md#434" + },{ + "url": "https://hackerone.com/reports/454365" + },{ + "url": "https://kb.pulsesecure.net/articles/Pulse_Security_Advisories/SA44601" + },{ + "url": "https://linux.oracle.com/cve/CVE-2019-11358.html" + },{ + "url": "https://linux.oracle.com/errata/ELSA-2020-4847.html" + },{ + "url": "https://lists.apache.org/thread.html/08720ef215ee7ab3386c05a1a90a7d1c852bf0706f176a7816bf65fc@%3Ccommits.airflow.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/519eb0fd45642dcecd9ff74cb3e71c20a4753f7d82e2f07864b5108f@%3Cdev.drill.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/5928aa293e39d248266472210c50f176cac1535220f2486e6a7fa844@%3Ccommits.airflow.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/6097cdbd6f0a337bedd9bb5cc441b2d525ff002a96531de367e4259f@%3Ccommits.airflow.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/88fb0362fd40e5b605ea8149f63241537b8b6fb5bfa315391fc5cbb7@%3Ccommits.airflow.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/b0656d359c7d40ec9f39c8cc61bca66802ef9a2a12ee199f5b0c1442@%3Cdev.drill.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/b736d0784cf02f5a30fbb4c5902762a15ad6d47e17e2c5a17b7d6205@%3Ccommits.airflow.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/ba79cf1658741e9f146e4c59b50aee56656ea95d841d358d006c18b6@%3Ccommits.roller.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/bcce5a9c532b386c68dab2f6b3ce8b0cc9b950ec551766e76391caa3@%3Ccommits.nifi.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/f9bc3e55f4e28d1dcd1a69aae6d53e609a758e34d2869b4d798e13cc@%3Cissues.drill.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/r2041a75d3fc09dec55adfd95d598b38d22715303f65c997c054844c9@%3Cissues.flink.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/r2baacab6e0acb5a2092eb46ae04fd6c3e8277b4fd79b1ffb7f3254fa@%3Cissues.flink.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/r38f0d1aa3c923c22977fe7376508f030f22e22c1379fbb155bf29766@%3Cdev.syncope.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/r41b5bfe009c845f67d4f68948cc9419ac2d62e287804aafd72892b08@%3Cissues.flink.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/r7aac081cbddb6baa24b75e74abf0929bf309b176755a53e3ed810355@%3Cdev.flink.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/r7d64895cc4dff84d0becfc572b20c0e4bf9bfa7b10c6f5f73e783734@%3Cdev.storm.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/r7e8ebccb7c022e41295f6fdb7b971209b83702339f872ddd8cf8bf73@%3Cissues.flink.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/rac25da84ecdcd36f6de5ad0d255f4e967209bbbebddb285e231da37d@%3Cissues.flink.apache.org%3E" + },{ + "url": "https://lists.apache.org/thread.html/rca37935d661f4689cb4119f1b3b224413b22be161b678e6e6ce0c69b@%3Ccommits.nifi.apache.org%3E" + },{ + "url": "https://lists.debian.org/debian-lts-announce/2019/05/msg00006.html" + },{ + "url": "https://lists.debian.org/debian-lts-announce/2019/05/msg00029.html" + },{ + "url": "https://lists.debian.org/debian-lts-announce/2020/02/msg00024.html" + },{ + "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/4UOAZIFCSZ3ENEFOR5IXX6NFAD3HV7FA/" + },{ + "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/5IABSKTYZ5JUGL735UKGXL5YPRYOPUYI/" + },{ + "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/KYH3OAGR2RTCHRA5NOKX2TES7SNQMWGO/" + },{ + "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/QV3PKZC3PQCO3273HAT76PAQZFBEO4KP/" + },{ + "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/RLXRX23725JL366CNZGJZ7AQQB7LHQ6F/" + },{ + "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/WZW27UCJ5CYFL4KFFFMYMIBNMIU2ALG5/" + },{ + "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-11358" + },{ + "url": "https://seclists.org/bugtraq/2019/Apr/32" + },{ + "url": "https://seclists.org/bugtraq/2019/Jun/12" + },{ + "url": "https://seclists.org/bugtraq/2019/May/18" + },{ + "url": "https://security.netapp.com/advisory/ntap-20190919-0001/" + },{ + "url": "https://snyk.io/vuln/SNYK-JS-JQUERY-174006" + },{ + "url": "https://www.debian.org/security/2019/dsa-4434" + },{ + "url": "https://www.debian.org/security/2019/dsa-4460" + },{ + "url": "https://www.drupal.org/sa-core-2019-006" + },{ + "url": "https://www.oracle.com//security-alerts/cpujul2021.html" + },{ + "url": "https://www.oracle.com/security-alerts/cpuApr2021.html" + },{ + "url": "https://www.oracle.com/security-alerts/cpuapr2020.html" + },{ + "url": "https://www.oracle.com/security-alerts/cpujan2020.html" + },{ + "url": "https://www.oracle.com/security-alerts/cpujan2021.html" + },{ + "url": "https://www.oracle.com/security-alerts/cpujul2020.html" + },{ + "url": "https://www.oracle.com/security-alerts/cpuoct2020.html" + },{ + "url": "https://www.oracle.com/security-alerts/cpuoct2021.html" + },{ + "url": "https://www.oracle.com/technetwork/security-advisory/cpujul2019-5072835.html" + },{ + "url": "https://www.oracle.com/technetwork/security-advisory/cpuoct2019-5072832.html" + },{ + "url": "https://www.privacy-wise.com/mitigating-cve-2019-11358-in-old-versions-of-jquery/" + },{ + "url": "https://www.synology.com/security/advisory/Synology_SA_19_19" + },{ + "url": "https://www.tenable.com/security/tns-2019-08" + },{ + "url": "https://www.tenable.com/security/tns-2020-02" + } + ] + } + ], + "remediations": [] +} From ad3c09e006e134f3c5b879ffc34ce9895a8c860f Mon Sep 17 00:00:00 2001 From: dean Date: Fri, 25 Oct 2024 07:02:00 +0100 Subject: [PATCH 66/94] feat: add end of life date for Ubuntu 24.10 (#7787) --- pkg/detector/ospkg/ubuntu/ubuntu.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/detector/ospkg/ubuntu/ubuntu.go b/pkg/detector/ospkg/ubuntu/ubuntu.go index b396d530d84e..8b36a2b1f87e 100644 --- a/pkg/detector/ospkg/ubuntu/ubuntu.go +++ b/pkg/detector/ospkg/ubuntu/ubuntu.go @@ -62,6 +62,7 @@ var ( "23.04": time.Date(2024, 1, 20, 23, 59, 59, 0, time.UTC), "23.10": time.Date(2024, 6, 30, 23, 59, 59, 0, time.UTC), "24.04": time.Date(2034, 3, 31, 23, 59, 59, 0, time.UTC), + "24.10": time.Date(2025, 7, 9, 23, 59, 59, 0, time.UTC), } ) From a16b830e00bac47ca61bcb929e0b4b89884953e9 Mon Sep 17 00:00:00 2001 From: afdesk Date: Fri, 25 Oct 2024 12:07:30 +0600 Subject: [PATCH 67/94] ci(helm): auto public Helm chart after PR merged (#7526) --- .github/workflows/bypass-test.yaml | 2 + .github/workflows/publish-chart.yaml | 46 +++++++++-- .github/workflows/test.yaml | 1 + magefiles/helm.go | 117 +++++++++++++++++++++++++++ magefiles/helm_test.go | 92 +++++++++++++++++++++ magefiles/magefile.go | 7 ++ 6 files changed, 260 insertions(+), 5 deletions(-) create mode 100644 magefiles/helm.go create mode 100644 magefiles/helm_test.go diff --git a/.github/workflows/bypass-test.yaml b/.github/workflows/bypass-test.yaml index 3a3102e3e574..93c5ba2869d3 100644 --- a/.github/workflows/bypass-test.yaml +++ b/.github/workflows/bypass-test.yaml @@ -9,6 +9,7 @@ on: - 'mkdocs.yml' - 'LICENSE' - '.release-please-manifest.json' + - 'helm/trivy/Chart.yaml' pull_request: paths: - '**.md' @@ -16,6 +17,7 @@ on: - 'mkdocs.yml' - 'LICENSE' - '.release-please-manifest.json' + - 'helm/trivy/Chart.yaml' jobs: test: name: Test diff --git a/.github/workflows/publish-chart.yaml b/.github/workflows/publish-chart.yaml index 3a7db4970065..15c8d84da31d 100644 --- a/.github/workflows/publish-chart.yaml +++ b/.github/workflows/publish-chart.yaml @@ -4,6 +4,11 @@ name: Publish Helm chart on: workflow_dispatch: pull_request: + types: + - opened + - synchronize + - reopened + - closed branches: - main paths: @@ -18,8 +23,10 @@ env: KIND_VERSION: "v0.14.0" KIND_IMAGE: "kindest/node:v1.23.6@sha256:b1fa224cc6c7ff32455e0b1fd9cbfd3d3bc87ecaa8fcb06961ed1afb3db0f9ae" jobs: + # `test-chart` job starts if a PR with Helm Chart is created, merged etc. test-chart: - runs-on: ubuntu-20.04 + if: github.event_name != 'push' + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4.1.6 @@ -28,11 +35,12 @@ jobs: - name: Install Helm uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 with: - version: v3.5.0 + version: v3.14.4 - name: Set up python uses: actions/setup-python@v5 with: - python-version: 3.7 + python-version: '3.x' + check-latest: true - name: Setup Chart Linting id: lint uses: helm/chart-testing-action@e6669bcd63d7cb57cb4380c33043eebe5d111992 @@ -48,11 +56,39 @@ jobs: sed -i -e '136s,false,'true',g' ./helm/trivy/values.yaml ct lint-and-install --validate-maintainers=false --charts helm/trivy + # `update-chart-version` job starts if a new tag is pushed + update-chart-version: + if: github.event_name == 'push' + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v4.1.6 + with: + fetch-depth: 0 + - name: Set up Git user + run: | + git config --global user.email "actions@github.com" + git config --global user.name "GitHub Actions" + + - name: Install tools + uses: aquaproj/aqua-installer@v3.0.1 + with: + aqua_version: v1.25.0 + aqua_opts: "" + + - name: Create a PR with Trivy version + run: mage helm:updateVersion + env: + # Use ORG_REPO_TOKEN instead of GITHUB_TOKEN + # This allows the created PR to trigger tests and other workflows + GITHUB_TOKEN: ${{ secrets.ORG_REPO_TOKEN }} + + # `publish-chart` job starts if a PR with a new Helm Chart is merged or manually publish-chart: - if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + if: github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch' needs: - test-chart - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4.1.6 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 8932a683c5bc..05edadf93331 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -7,6 +7,7 @@ on: - 'mkdocs.yml' - 'LICENSE' - '.release-please-manifest.json' ## don't run tests for release-please PRs + - 'helm/trivy/Chart.yaml' merge_group: workflow_dispatch: diff --git a/magefiles/helm.go b/magefiles/helm.go new file mode 100644 index 000000000000..443c57eed029 --- /dev/null +++ b/magefiles/helm.go @@ -0,0 +1,117 @@ +//go:build mage_helm + +package main + +import ( + "fmt" + "log" + "os" + + "github.com/aquasecurity/go-version/pkg/semver" + + "github.com/magefile/mage/sh" + "golang.org/x/xerrors" + "gopkg.in/yaml.v3" +) + +const chartFile = "./helm/trivy/Chart.yaml" + +func main() { + trivyVersion, err := version() + if err != nil { + log.Fatalf("could not determine Trivy version: %v", err) + } + + newHelmVersion, err := bumpHelmChart(chartFile, trivyVersion) + if err != nil { + log.Fatalf("could not bump Trivy version to %q: %v", trivyVersion, err) + } + + log.Printf("Current helm version will bump up %q with Trivy %q", newHelmVersion, trivyVersion) + + newBranch := fmt.Sprintf("ci/helm-chart/bump-trivy-to-%s", trivyVersion) + title := fmt.Sprintf("ci(helm): bump Trivy version to %s for Trivy Helm Chart %s", trivyVersion, newHelmVersion) + description := fmt.Sprintf("This PR bumps Trivy up to the %s version for the Trivy Helm chart %s.", + trivyVersion, newHelmVersion) + + cmds := [][]string{ + []string{"git", "switch", "-c", newBranch}, + []string{"git", "add", chartFile}, + []string{"git", "commit", "-m", title}, + []string{"git", "push", "origin", newBranch}, + []string{"gh", "pr", "create", "--base", "main", "--head", newBranch, "--title", title, "--body", description, "--repo", "$GITHUB_REPOSITORY"}, + } + + if err := runShCommands(cmds); err != nil { + log.Fatal(err) + } + log.Print("Successfully created PR with a new helm version") +} + +type Chart struct { + Version string `yaml:"version"` + AppVersion string `yaml:"appVersion"` +} + +// bumpHelmChart bumps up helm and trivy versions inside a file (Chart.yaml) +// it returns a new helm version and error +func bumpHelmChart(filename, trivyVersion string) (string, error) { + input, err := os.ReadFile(filename) + if err != nil { + return "", xerrors.Errorf("could not read file %q: %w", filename, err) + } + currentHelmChart := &Chart{} + if err := yaml.Unmarshal(input, currentHelmChart); err != nil { + return "", xerrors.Errorf("could not unmarshal helm chart %q: %w", filename, err) + } + + newHelmVersion, err := buildNewHelmVersion(currentHelmChart.Version, currentHelmChart.AppVersion, trivyVersion) + if err != nil { + return "", xerrors.Errorf("could not build new helm version: %v", err) + } + cmds := [][]string{ + []string{"sed", "-i", "-e", fmt.Sprintf("s/appVersion: %s/appVersion: %s/g", currentHelmChart.AppVersion, trivyVersion), filename}, + []string{"sed", "-i", "-e", fmt.Sprintf("s/version: %s/version: %s/g", currentHelmChart.Version, newHelmVersion), filename}, + } + + if err := runShCommands(cmds); err != nil { + return "", xerrors.Errorf("could not update Helm Chart %q: %w", newHelmVersion, err) + } + return newHelmVersion, nil +} + +func runShCommands(cmds [][]string) error { + for _, cmd := range cmds { + if err := sh.Run(cmd[0], cmd[1:]...); err != nil { + return xerrors.Errorf("failed to run %v: %w", cmd, err) + } + } + return nil +} + +func buildNewHelmVersion(currentHelm, currentTrivy, newTrivy string) (string, error) { + currentHelmVersion, err := semver.Parse(currentHelm) + if err != nil { + return "", xerrors.Errorf("could not parse current helm version: %w", err) + } + + currentTrivyVersion, err := semver.Parse(currentTrivy) + if err != nil { + return "", xerrors.Errorf("could not parse current trivy version: %w", err) + } + + newTrivyVersion, err := semver.Parse(newTrivy) + if err != nil { + return "", xerrors.Errorf("could not parse new trivy version: %w", err) + } + + if newTrivyVersion.Major().Compare(currentTrivyVersion.Major()) > 0 { + return currentHelmVersion.IncMajor().String(), nil + } + + if newTrivyVersion.Minor().Compare(currentTrivyVersion.Minor()) > 0 { + return currentHelmVersion.IncMinor().String(), nil + } + + return currentHelmVersion.IncPatch().String(), nil +} diff --git a/magefiles/helm_test.go b/magefiles/helm_test.go new file mode 100644 index 000000000000..f2e3233d2879 --- /dev/null +++ b/magefiles/helm_test.go @@ -0,0 +1,92 @@ +//go:build mage_helm + +package main + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNewVersion(t *testing.T) { + tests := []struct { + name string + currentHelmVersion string + currentTrivyVersion string + newTrivyVersion string + newHelmVersion string + }{ + { + "created the first patch", + "0.1.0", + "0.55.0", + "0.55.1", + "0.1.1", + }, + { + "created the second patch", + "0.1.1", + "0.55.1", + "0.55.2", + "0.1.2", + }, + { + "created the second patch but helm chart was changed", + "0.1.2", + "0.55.1", + "0.55.2", + "0.1.3", + }, + { + "created a new minor version", + "0.1.1", + "0.55.1", + "0.56.0", + "0.2.0", + }, + { + "created a new major version", + "0.1.1", + "0.55.1", + "1.0.0", + "1.0.0", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + newHelmVersion, err := buildNewHelmVersion(test.currentHelmVersion, test.currentTrivyVersion, test.newTrivyVersion) + assert.NoError(t, err) + assert.Equal(t, test.newHelmVersion, newHelmVersion) + }) + } +} + +func TestBumpHelmChart_Success(t *testing.T) { + tempFile, err := os.CreateTemp(t.TempDir(), "Chart-*.yaml") + assert.NoError(t, err) + + content := ` +apiVersion: v2 +name: trivy +version: 0.8.0 +appVersion: 0.55.0 +description: Trivy helm chart +keywords: + - scanner + - trivy + - vulnerability +` + err = os.WriteFile(tempFile.Name(), []byte(content), 0644) + assert.NoError(t, err) + + newVersion, err := bumpHelmChart(tempFile.Name(), "0.55.1") + assert.NoError(t, err) + assert.Equal(t, "0.8.1", newVersion) + + updatedContent, err := os.ReadFile(tempFile.Name()) + assert.NoError(t, err) + assert.Contains(t, string(updatedContent), "appVersion: 0.55.1") + assert.Contains(t, string(updatedContent), "version: 0.8.1") +} diff --git a/magefiles/magefile.go b/magefiles/magefile.go index 06ebd7e665e1..f70491bce2e8 100644 --- a/magefiles/magefile.go +++ b/magefiles/magefile.go @@ -489,3 +489,10 @@ func (CloudActions) Generate() error { func VEX(_ context.Context, dir string) error { return sh.RunWith(ENV, "go", "run", "-tags=mage_vex", "./magefiles/vex.go", "--dir", dir) } + +type Helm mg.Namespace + +// UpdateVersion updates a version for Trivy Helm Chart and creates a PR +func (Helm) UpdateVersion() error { + return sh.RunWith(ENV, "go", "run", "-tags=mage_helm", "./magefiles") +} From 63dd3d65a32296eee529c41c41f3221e2cd6d3fe Mon Sep 17 00:00:00 2001 From: okamototk Date: Mon, 28 Oct 2024 15:26:13 +0900 Subject: [PATCH 68/94] docs: add Windows install instructions (#7800) --- docs/getting-started/installation.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index fd8b19366e86..6e3c8cd0cfd2 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -56,6 +56,13 @@ Homebrew for MacOS and Linux. brew install trivy ``` +### Windows (Official) + +1. Download trivy_x.xx.x_windows-64bit.zip file from [releases page](https://github.com/aquasecurity/trivy/releases/). +2. Unzip file and copy to any folder. +3. Ensure PATH environment variable is configured to folder trivy installed. + + ### Arch Linux (Community) Arch Linux Package Repository. From 7a4f4d8b12996687f3095a2042cdf2f5985332c9 Mon Sep 17 00:00:00 2001 From: afdesk Date: Tue, 29 Oct 2024 13:08:13 +0600 Subject: [PATCH 69/94] fix(k8s): support kubernetes v1.31 (#7810) --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 1611c8c7080a..efc9daa926c9 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/aquasecurity/trivy-checks v1.1.0 github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1 github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 - github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240707095038-0300bc49b68b + github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241029051843-2606b7e0f0b4 github.com/aws/aws-sdk-go-v2 v1.31.0 github.com/aws/aws-sdk-go-v2/config v1.27.38 github.com/aws/aws-sdk-go-v2/credentials v1.17.36 @@ -131,7 +131,7 @@ require ( google.golang.org/protobuf v1.34.2 gopkg.in/yaml.v3 v3.0.1 helm.sh/helm/v3 v3.16.1 - k8s.io/api v0.31.0 + k8s.io/api v0.31.2 k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 modernc.org/sqlite v1.33.1 sigs.k8s.io/yaml v1.4.0 @@ -173,7 +173,7 @@ require ( github.com/antchfx/xpath v1.3.1 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go v1.54.6 // indirect + github.com/aws/aws-sdk-go v1.55.5 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 // indirect @@ -402,14 +402,14 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/apiextensions-apiserver v0.31.0 // indirect - k8s.io/apimachinery v0.31.0 // indirect + k8s.io/apimachinery v0.31.2 // indirect k8s.io/apiserver v0.31.0 // indirect - k8s.io/cli-runtime v0.31.0 // indirect - k8s.io/client-go v0.31.0 // indirect - k8s.io/component-base v0.31.0 // indirect + k8s.io/cli-runtime v0.31.2 // indirect + k8s.io/client-go v0.31.2 // indirect + k8s.io/component-base v0.31.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/kubectl v0.31.0 // indirect + k8s.io/kubectl v0.31.2 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect modernc.org/libc v1.55.3 // indirect modernc.org/mathutil v1.6.0 // indirect diff --git a/go.sum b/go.sum index 51d43bf95aa1..153c1ab02dea 100644 --- a/go.sum +++ b/go.sum @@ -355,8 +355,8 @@ github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1 h1:G0gnacAOR github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1/go.mod h1:PYkSRx4dlgFATEt+okGwibvbxVEtqsOdH+vX/saACYE= github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 h1:JVgBIuIYbwG+ekC5lUHUpGJboPYiCcxiz06RCtz8neI= github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48/go.mod h1:Ldya37FLi0e/5Cjq2T5Bty7cFkzUDwTcPeQua+2M8i8= -github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240707095038-0300bc49b68b h1:h7gsIzHyrxpQnayOuQI0kX7+8rVcqhV6G5bM3KVFyJU= -github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240707095038-0300bc49b68b/go.mod h1:HOhrqoyIeTxpwnKr1EyWtQ+rt2XahV8b0UDBrRpSfEQ= +github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241029051843-2606b7e0f0b4 h1:i0Z0JS4xtMAcBVOpYSciS7slmIBi1SmjT6garbrJtcA= +github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241029051843-2606b7e0f0b4/go.mod h1:ctlibFXOQyjWybeVVQI6NLG6GJoPWZJ4cIirQ/wPCQs= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= @@ -364,8 +364,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.54.6 h1:HEYUib3yTt8E6vxjMWM3yAq5b+qjj/6aKA62mkgux9g= -github.com/aws/aws-sdk-go v1.54.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= +github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/aws/aws-sdk-go-v2 v1.31.0 h1:3V05LbxTSItI5kUqNwhJrrrY1BAXxXt0sN0l72QmG5U= github.com/aws/aws-sdk-go-v2 v1.31.0/go.mod h1:ztolYtaEUtdpf9Wftr31CJfLVjOnD/CVRkKOOYgF8hA= github.com/aws/aws-sdk-go-v2/config v1.27.38 h1:mMVyJJuSUdbD4zKXoxDgWrgM60QwlFEg+JhihCq6wCw= @@ -2076,26 +2076,26 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo= -k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE= +k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= +k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= -k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= -k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= +k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= k8s.io/apiserver v0.31.0 h1:p+2dgJjy+bk+B1Csz+mc2wl5gHwvNkC9QJV+w55LVrY= k8s.io/apiserver v0.31.0/go.mod h1:KI9ox5Yu902iBnnyMmy7ajonhKnkeZYJhTZ/YI+WEMk= -k8s.io/cli-runtime v0.31.0 h1:V2Q1gj1u3/WfhD475HBQrIYsoryg/LrhhK4RwpN+DhA= -k8s.io/cli-runtime v0.31.0/go.mod h1:vg3H94wsubuvWfSmStDbekvbla5vFGC+zLWqcf+bGDw= -k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8= -k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU= -k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs= -k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo= +k8s.io/cli-runtime v0.31.2 h1:7FQt4C4Xnqx8V1GJqymInK0FFsoC+fAZtbLqgXYVOLQ= +k8s.io/cli-runtime v0.31.2/go.mod h1:XROyicf+G7rQ6FQJMbeDV9jqxzkWXTYD6Uxd15noe0Q= +k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= +k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs= +k8s.io/component-base v0.31.2 h1:Z1J1LIaC0AV+nzcPRFqfK09af6bZ4D1nAOpWsy9owlA= +k8s.io/component-base v0.31.2/go.mod h1:9PeyyFN/drHjtJZMCTkSpQJS3U9OXORnHQqMLDz0sUQ= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/kubectl v0.31.0 h1:kANwAAPVY02r4U4jARP/C+Q1sssCcN/1p9Nk+7BQKVg= -k8s.io/kubectl v0.31.0/go.mod h1:pB47hhFypGsaHAPjlwrNbvhXgmuAr01ZBvAIIUaI8d4= +k8s.io/kubectl v0.31.2 h1:gTxbvRkMBwvTSAlobiTVqsH6S8Aa1aGyBcu5xYLsn8M= +k8s.io/kubectl v0.31.2/go.mod h1:EyASYVU6PY+032RrTh5ahtSOMgoDRIux9V1JLKtG5xM= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= From c4347759234dcb5f372b07f92fb4230ef391d710 Mon Sep 17 00:00:00 2001 From: smtan-gl <139748976+smtan-gl@users.noreply.github.com> Date: Tue, 29 Oct 2024 15:26:28 +0800 Subject: [PATCH 70/94] fix(k8s)!: support k8s multi container (#7444) Co-authored-by: afdesk --- pkg/k8s/report/report.go | 16 +-- pkg/k8s/report/report_test.go | 185 ++++++++++++++++++++++++++++------ 2 files changed, 165 insertions(+), 36 deletions(-) diff --git a/pkg/k8s/report/report.go b/pkg/k8s/report/report.go index e71c218bf864..b52391ec8239 100644 --- a/pkg/k8s/report/report.go +++ b/pkg/k8s/report/report.go @@ -57,9 +57,9 @@ type Resource struct { Namespace string `json:",omitempty"` Kind string Name string - Metadata types.Metadata `json:",omitempty"` - Results types.Results `json:",omitempty"` - Error string `json:",omitempty"` + Metadata []types.Metadata `json:",omitempty"` + Results types.Results `json:",omitempty"` + Error string `json:",omitempty"` // original report Report types.Report `json:"-"` @@ -99,11 +99,15 @@ func (r Report) consolidate() ConsolidatedReport { key := v.fullname() if res, ok := index[key]; ok { + // Combine metadata + metadata := lo.UniqBy(append(res.Metadata, v.Metadata...), func(x types.Metadata) string { + return x.ImageID + }) index[key] = Resource{ Namespace: res.Namespace, Kind: res.Kind, Name: res.Name, - Metadata: res.Metadata, + Metadata: metadata, Results: append(res.Results, v.Results...), Error: res.Error, } @@ -214,7 +218,7 @@ func infraResource(misConfig Resource) bool { func CreateResource(artifact *artifacts.Artifact, report types.Report, err error) Resource { r := createK8sResource(artifact, report.Results) - r.Metadata = report.Metadata + r.Metadata = []types.Metadata{report.Metadata} r.Report = report // if there was any error during the scan if err != nil { @@ -244,7 +248,7 @@ func createK8sResource(artifact *artifacts.Artifact, scanResults types.Results) Namespace: artifact.Namespace, Kind: artifact.Kind, Name: artifact.Name, - Metadata: types.Metadata{}, + Metadata: []types.Metadata{}, Results: results, Report: types.Report{ Results: results, diff --git a/pkg/k8s/report/report_test.go b/pkg/k8s/report/report_test.go index e9e9ae5e3a91..1a984eb71b23 100644 --- a/pkg/k8s/report/report_test.go +++ b/pkg/k8s/report/report_test.go @@ -14,12 +14,15 @@ var ( Namespace: "default", Kind: "Deploy", Name: "orion", - Metadata: types.Metadata{ - RepoTags: []string{ - "alpine:3.14", - }, - RepoDigests: []string{ - "alpine:3.14@sha256:8fe1727132b2506c17ba0e1f6a6ed8a016bb1f5735e43b2738cd3fd1979b6260", + Metadata: []types.Metadata{ + { + ImageID: "123", + RepoTags: []string{ + "alpine:3.14", + }, + RepoDigests: []string{ + "alpine:3.14@sha256:8fe1727132b2506c17ba0e1f6a6ed8a016bb1f5735e43b2738cd3fd1979b6260", + }, }, }, Results: types.Results{ @@ -69,12 +72,15 @@ var ( Namespace: "default", Kind: "Deploy", Name: "orion", - Metadata: types.Metadata{ - RepoTags: []string{ - "alpine:3.14", - }, - RepoDigests: []string{ - "alpine:3.14@sha256:8fe1727132b2506c17ba0e1f6a6ed8a016bb1f5735e43b2738cd3fd1979b6260", + Metadata: []types.Metadata{ + { + ImageID: "123", + RepoTags: []string{ + "alpine:3.14", + }, + RepoDigests: []string{ + "alpine:3.14@sha256:8fe1727132b2506c17ba0e1f6a6ed8a016bb1f5735e43b2738cd3fd1979b6260", + }, }, }, Results: types.Results{ @@ -113,16 +119,117 @@ var ( }, } + image1WithVulns = Resource{ + Namespace: "default", + Kind: "Pod", + Name: "multi-image-pod", + Metadata: []types.Metadata{ + { + ImageID: "image1", + RepoTags: []string{ + "alpine:3.14", + }, + RepoDigests: []string{ + "alpine:3.14@sha256:8fe1727132b2506c17ba0e1f6a6ed8a016bb1f5735e43b2738cd3fd1979b6260", + }, + }, + }, + Results: types.Results{ + { + Vulnerabilities: []types.DetectedVulnerability{ + { + VulnerabilityID: "CVE-2022-1111", + Vulnerability: dbTypes.Vulnerability{Severity: "LOW"}, + }, + }, + }, + }, + } + + image2WithVulns = Resource{ + Namespace: "default", + Kind: "Pod", + Name: "multi-image-pod", + Metadata: []types.Metadata{ + { + ImageID: "image2", + RepoTags: []string{ + "alpine:3.17.3", + }, + RepoDigests: []string{ + "alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126", + }, + }, + }, + Results: types.Results{ + { + Vulnerabilities: []types.DetectedVulnerability{ + { + VulnerabilityID: "CVE-2022-2222", + Vulnerability: dbTypes.Vulnerability{Severity: "MEDIUM"}, + }, + }, + }, + }, + } + + multiImagePodWithVulns = Resource{ + Namespace: "default", + Kind: "Pod", + Name: "multi-image-pod", + Metadata: []types.Metadata{ + { + ImageID: "image1", + RepoTags: []string{ + "alpine:3.14", + }, + RepoDigests: []string{ + "alpine:3.14@sha256:8fe1727132b2506c17ba0e1f6a6ed8a016bb1f5735e43b2738cd3fd1979b6260", + }, + }, + { + ImageID: "image2", + RepoTags: []string{ + "alpine:3.17.3", + }, + RepoDigests: []string{ + "alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126", + }, + }, + }, + Results: types.Results{ + { + Vulnerabilities: []types.DetectedVulnerability{ + { + VulnerabilityID: "CVE-2022-1111", + Vulnerability: dbTypes.Vulnerability{Severity: "LOW"}, + }, + }, + }, + { + Vulnerabilities: []types.DetectedVulnerability{ + { + VulnerabilityID: "CVE-2022-2222", + Vulnerability: dbTypes.Vulnerability{Severity: "MEDIUM"}, + }, + }, + }, + }, + } + deployOrionWithBothVulnsAndMisconfigs = Resource{ Namespace: "default", Kind: "Deploy", Name: "orion", - Metadata: types.Metadata{ - RepoTags: []string{ - "alpine:3.14", - }, - RepoDigests: []string{ - "alpine:3.14@sha256:8fe1727132b2506c17ba0e1f6a6ed8a016bb1f5735e43b2738cd3fd1979b6260", + Metadata: []types.Metadata{ + { + ImageID: "123", + RepoTags: []string{ + "alpine:3.14", + }, + RepoDigests: []string{ + "alpine:3.14@sha256:8fe1727132b2506c17ba0e1f6a6ed8a016bb1f5735e43b2738cd3fd1979b6260", + }, }, }, Results: types.Results{ @@ -204,12 +311,15 @@ var ( Namespace: "default", Kind: "Cronjob", Name: "hello", - Metadata: types.Metadata{ - RepoTags: []string{ - "alpine:3.14", - }, - RepoDigests: []string{ - "alpine:3.14@sha256:8fe1727132b2506c17ba0e1f6a6ed8a016bb1f5735e43b2738cd3fd1979b6260", + Metadata: []types.Metadata{ + { + ImageID: "123", + RepoTags: []string{ + "alpine:3.14", + }, + RepoDigests: []string{ + "alpine:3.14@sha256:8fe1727132b2506c17ba0e1f6a6ed8a016bb1f5735e43b2738cd3fd1979b6260", + }, }, }, Results: types.Results{ @@ -221,12 +331,15 @@ var ( Namespace: "default", Kind: "Pod", Name: "prometheus", - Metadata: types.Metadata{ - RepoTags: []string{ - "alpine:3.14", - }, - RepoDigests: []string{ - "alpine:3.14@sha256:8fe1727132b2506c17ba0e1f6a6ed8a016bb1f5735e43b2738cd3fd1979b6260", + Metadata: []types.Metadata{ + { + ImageID: "123", + RepoTags: []string{ + "alpine:3.14", + }, + RepoDigests: []string{ + "alpine:3.14@sha256:8fe1727132b2506c17ba0e1f6a6ed8a016bb1f5735e43b2738cd3fd1979b6260", + }, }, }, Results: types.Results{ @@ -358,6 +471,18 @@ func TestReport_consolidate(t *testing.T) { "default/cronjob/hello": cronjobHelloWithVulns, }, }, + { + name: "report with multi image pod containing vulnerabilities", + report: Report{ + Resources: []Resource{ + image1WithVulns, + image2WithVulns, + }, + }, + expectedFindings: map[string]Resource{ + "default/pod/multi-image-pod": multiImagePodWithVulns, + }, + }, } for _, tt := range tests { From c70b6fa16613fa5482fe4ece9859b2cf60752977 Mon Sep 17 00:00:00 2001 From: simar7 <1254783+simar7@users.noreply.github.com> Date: Tue, 29 Oct 2024 16:29:42 -0600 Subject: [PATCH 71/94] refactor(misconf): Deprecate `EXCEPTIONS` for misconfiguration scanning (#7776) Signed-off-by: Simar --- contrib/junit.tpl | 2 +- docs/docs/configuration/filtering.md | 6 +- .../configuration/cli/trivy_config.md | 2 +- .../configuration/cli/trivy_filesystem.md | 2 +- .../configuration/cli/trivy_image.md | 2 +- .../configuration/cli/trivy_kubernetes.md | 2 +- .../configuration/cli/trivy_repository.md | 2 +- .../configuration/cli/trivy_rootfs.md | 2 +- .../references/configuration/cli/trivy_vm.md | 2 +- .../misconfiguration/check/exceptions.md | 92 --- .../scanner/misconfiguration/custom/debug.md | 2 +- .../scanner/misconfiguration/custom/index.md | 2 +- docs/docs/scanner/misconfiguration/index.md | 22 +- docs/docs/target/container_image.md | 2 +- docs/docs/target/kubernetes.md | 3 +- integration/repo_test.go | 9 - .../dockerfile-custom-policies.json.golden | 3 +- ...dockerfile-namespace-exception.json.golden | 30 - .../dockerfile-rule-exception.json.golden | 3 +- integration/testdata/dockerfile.json.golden | 3 +- .../dockerfile_file_pattern.json.golden | 3 +- .../repo/namespace-exception/Dockerfile | 2 - .../namespace-exception/policy/exception.rego | 8 - integration/testdata/helm.json.golden | 3 +- .../testdata/helm_testchart.json.golden | 9 +- .../helm_testchart.overridden.json.golden | 9 +- mkdocs.yml | 1 - pkg/cache/mock_artifact_cache.go | 3 - pkg/compliance/report/report_test.go | 10 +- pkg/compliance/report/testdata/table_all.txt | 24 +- pkg/compliance/spec/mapper.go | 2 - pkg/compliance/spec/mapper_test.go | 10 +- pkg/fanal/types/misconf.go | 14 +- pkg/flag/misconf_flags.go | 2 +- pkg/iac/rego/exceptions.go | 35 - pkg/iac/rego/scanner.go | 25 +- pkg/iac/rego/scanner_test.go | 162 ----- pkg/iac/scanners/cloudformation/scanner.go | 1 + .../scanners/terraform/executor/executor.go | 1 + pkg/misconf/scanner.go | 2 - pkg/report/table/misconfig.go | 4 +- pkg/report/table/misconfig_test.go | 19 +- pkg/result/filter.go | 6 +- pkg/result/filter_test.go | 20 +- pkg/rpc/convert.go | 24 +- pkg/scanner/local/scan.go | 3 - pkg/scanner/local/scan_test.go | 23 - pkg/types/report.go | 7 +- rpc/cache/service.pb.go | 2 +- rpc/common/service.pb.go | 665 +++++++++--------- rpc/common/service.proto | 3 +- 51 files changed, 430 insertions(+), 865 deletions(-) delete mode 100644 docs/docs/scanner/misconfiguration/check/exceptions.md delete mode 100644 integration/testdata/dockerfile-namespace-exception.json.golden delete mode 100644 integration/testdata/fixtures/repo/namespace-exception/Dockerfile delete mode 100644 integration/testdata/fixtures/repo/namespace-exception/policy/exception.rego delete mode 100644 pkg/iac/rego/exceptions.go diff --git a/contrib/junit.tpl b/contrib/junit.tpl index b01bb9fd22dd..27b654b7b049 100644 --- a/contrib/junit.tpl +++ b/contrib/junit.tpl @@ -16,7 +16,7 @@ {{- if .MisconfSummary }} - + {{- else }} {{- end }} diff --git a/docs/docs/configuration/filtering.md b/docs/docs/configuration/filtering.md index befcc54180ac..22fbe2d7a24d 100644 --- a/docs/docs/configuration/filtering.md +++ b/docs/docs/configuration/filtering.md @@ -112,7 +112,7 @@ trivy config --severity HIGH,CRITICAL examples/misconf/mixed Dockerfile (dockerfile) ======================= -Tests: 17 (SUCCESSES: 16, FAILURES: 1, EXCEPTIONS: 0) +Tests: 17 (SUCCESSES: 16, FAILURES: 1) Failures: 1 (HIGH: 1, CRITICAL: 0) HIGH: Last USER command in Dockerfile should not be 'root' @@ -130,13 +130,13 @@ See https://avd.aquasec.com/misconfig/ds002 deployment.yaml (kubernetes) ============================ -Tests: 8 (SUCCESSES: 8, FAILURES: 0, EXCEPTIONS: 0) +Tests: 8 (SUCCESSES: 8, FAILURES: 0) Failures: 0 (HIGH: 0, CRITICAL: 0) main.tf (terraform) =================== -Tests: 1 (SUCCESSES: 0, FAILURES: 1, EXCEPTIONS: 0) +Tests: 1 (SUCCESSES: 0, FAILURES: 1) Failures: 1 (HIGH: 0, CRITICAL: 1) CRITICAL: Classic resources should not be used. diff --git a/docs/docs/references/configuration/cli/trivy_config.md b/docs/docs/references/configuration/cli/trivy_config.md index 0c279f1e7bf3..804b33725522 100644 --- a/docs/docs/references/configuration/cli/trivy_config.md +++ b/docs/docs/references/configuration/cli/trivy_config.md @@ -32,7 +32,7 @@ trivy config [flags] DIR --ignore-policy string specify the Rego file path to evaluate each vulnerability --ignorefile string specify .trivyignore file (default ".trivyignore") --include-deprecated-checks include deprecated checks - --include-non-failures include successes and exceptions, available with '--scanners misconfig' + --include-non-failures include successes, available with '--scanners misconfig' --k8s-version string specify k8s version to validate outdated api by it (example: 1.21.0) --misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot]) --module-dir string specify directory to the wasm modules that will be loaded (default "$HOME/.trivy/modules") diff --git a/docs/docs/references/configuration/cli/trivy_filesystem.md b/docs/docs/references/configuration/cli/trivy_filesystem.md index bbd5257d5f5d..dd1b2cd7a2e4 100644 --- a/docs/docs/references/configuration/cli/trivy_filesystem.md +++ b/docs/docs/references/configuration/cli/trivy_filesystem.md @@ -55,7 +55,7 @@ trivy filesystem [flags] PATH --ignorefile string specify .trivyignore file (default ".trivyignore") --include-deprecated-checks include deprecated checks --include-dev-deps include development dependencies in the report (supported: npm, yarn) - --include-non-failures include successes and exceptions, available with '--scanners misconfig' + --include-non-failures include successes, available with '--scanners misconfig' --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --license-confidence-level float specify license classifier's confidence level (default 0.9) --license-full eagerly look for licenses in source code headers and license files diff --git a/docs/docs/references/configuration/cli/trivy_image.md b/docs/docs/references/configuration/cli/trivy_image.md index 779b54f4d5b9..4a76ca742cad 100644 --- a/docs/docs/references/configuration/cli/trivy_image.md +++ b/docs/docs/references/configuration/cli/trivy_image.md @@ -72,7 +72,7 @@ trivy image [flags] IMAGE_NAME --image-config-scanners strings comma-separated list of what security issues to detect on container image configurations (misconfig,secret) --image-src strings image source(s) to use, in priority order (docker,containerd,podman,remote) (default [docker,containerd,podman,remote]) --include-deprecated-checks include deprecated checks - --include-non-failures include successes and exceptions, available with '--scanners misconfig' + --include-non-failures include successes, available with '--scanners misconfig' --input string input file path instead of image name --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --license-confidence-level float specify license classifier's confidence level (default 0.9) diff --git a/docs/docs/references/configuration/cli/trivy_kubernetes.md b/docs/docs/references/configuration/cli/trivy_kubernetes.md index 6b8058cc00f0..1a25e859c3c8 100644 --- a/docs/docs/references/configuration/cli/trivy_kubernetes.md +++ b/docs/docs/references/configuration/cli/trivy_kubernetes.md @@ -69,7 +69,7 @@ trivy kubernetes [flags] [CONTEXT] --include-deprecated-checks include deprecated checks --include-kinds strings indicate the kinds included in scanning (example: node) --include-namespaces strings indicate the namespaces included in scanning (example: kube-system) - --include-non-failures include successes and exceptions, available with '--scanners misconfig' + --include-non-failures include successes, available with '--scanners misconfig' --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --k8s-version string specify k8s version to validate outdated api by it (example: 1.21.0) --kubeconfig string specify the kubeconfig file path to use diff --git a/docs/docs/references/configuration/cli/trivy_repository.md b/docs/docs/references/configuration/cli/trivy_repository.md index 190640f5cb2a..5936e0c34a61 100644 --- a/docs/docs/references/configuration/cli/trivy_repository.md +++ b/docs/docs/references/configuration/cli/trivy_repository.md @@ -55,7 +55,7 @@ trivy repository [flags] (REPO_PATH | REPO_URL) --ignorefile string specify .trivyignore file (default ".trivyignore") --include-deprecated-checks include deprecated checks --include-dev-deps include development dependencies in the report (supported: npm, yarn) - --include-non-failures include successes and exceptions, available with '--scanners misconfig' + --include-non-failures include successes, available with '--scanners misconfig' --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --license-confidence-level float specify license classifier's confidence level (default 0.9) --license-full eagerly look for licenses in source code headers and license files diff --git a/docs/docs/references/configuration/cli/trivy_rootfs.md b/docs/docs/references/configuration/cli/trivy_rootfs.md index 2f37484d0328..acd1d529a8ef 100644 --- a/docs/docs/references/configuration/cli/trivy_rootfs.md +++ b/docs/docs/references/configuration/cli/trivy_rootfs.md @@ -57,7 +57,7 @@ trivy rootfs [flags] ROOTDIR --ignored-licenses strings specify a list of license to ignore --ignorefile string specify .trivyignore file (default ".trivyignore") --include-deprecated-checks include deprecated checks - --include-non-failures include successes and exceptions, available with '--scanners misconfig' + --include-non-failures include successes, available with '--scanners misconfig' --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --license-confidence-level float specify license classifier's confidence level (default 0.9) --license-full eagerly look for licenses in source code headers and license files diff --git a/docs/docs/references/configuration/cli/trivy_vm.md b/docs/docs/references/configuration/cli/trivy_vm.md index 14ce8b78c21a..d4e3692f7e1c 100644 --- a/docs/docs/references/configuration/cli/trivy_vm.md +++ b/docs/docs/references/configuration/cli/trivy_vm.md @@ -51,7 +51,7 @@ trivy vm [flags] VM_IMAGE --ignore-status strings comma-separated list of vulnerability status to ignore (unknown,not_affected,affected,fixed,under_investigation,will_not_fix,fix_deferred,end_of_life) --ignore-unfixed display only fixed vulnerabilities --ignorefile string specify .trivyignore file (default ".trivyignore") - --include-non-failures include successes and exceptions, available with '--scanners misconfig' + --include-non-failures include successes, available with '--scanners misconfig' --java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [ghcr.io/aquasecurity/trivy-java-db:1]) --list-all-pkgs output all packages in the JSON report regardless of vulnerability --misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot]) diff --git a/docs/docs/scanner/misconfiguration/check/exceptions.md b/docs/docs/scanner/misconfiguration/check/exceptions.md deleted file mode 100644 index 70ef974a4b74..000000000000 --- a/docs/docs/scanner/misconfiguration/check/exceptions.md +++ /dev/null @@ -1,92 +0,0 @@ -# Exceptions -Exceptions let you specify cases where you allow policy violations. -Trivy supports two types of exceptions. - -!!! info - Exceptions can be applied to built-in checks as well as custom checks. - -## Namespace-based exceptions -There are some cases where you need to disable built-in checks partially or fully. -Namespace-based exceptions lets you rough choose which individual packages to exempt. - -To use namespace-based exceptions, create a Rego rule with the name `exception` that returns the package names to exempt. -The `exception` rule must be defined under `namespace.exceptions`. -`data.namespaces` includes all package names. - - -!!! example - ``` rego - package namespace.exceptions - - import data.namespaces - - exception[ns] { - ns := data.namespaces[_] - startswith(ns, "builtin.kubernetes") - } - ``` - -This example exempts all built-in checks for Kubernetes. - -## Rule-based exceptions -There are some cases where you need more flexibility and granularity in defining which cases to exempt. -Rule-based exceptions lets you granularly choose which individual rules to exempt, while also declaring under which conditions to exempt them. - -To use rule-based exceptions, create a Rego rule with the name `exception` that returns the rule name suffixes to exempt, prefixed by `deny_` (for example, returning `foo` will exempt `deny_foo`). -The rule can make any other assertion, for example, on the input or data documents. -This is useful to specify the exemption for a specific case. - -Note that if you specify the empty string, the exception will match all rules named `deny`. - -``` -exception[rules] { - # Logic - - rules = ["foo","bar"] -} -``` - -The above would provide an exception from `deny_foo` and `deny_bar`. - - -!!! example - ``` - package user.kubernetes.ID100 - - __rego_metadata := { - "id": "ID100", - "title": "Deployment not allowed", - "severity": "HIGH", - "type": "Kubernetes Custom Check", - } - - deny_deployment[msg] { - input.kind == "Deployment" - msg = sprintf("Found deployment '%s' but deployments are not allowed", [name]) - } - - exception[rules] { - input.kind == "Deployment" - input.metadata.name == "allow-deployment" - - rules := ["deployment"] - } - ``` - -If you want to apply rule-based exceptions to built-in checks, you have to define the exception under the same package. - -!!! example - ``` rego - package builtin.kubernetes.KSV012 - - exception[rules] { - input.metadata.name == "can-run-as-root" - rules := [""] - } - ``` - -This exception is applied to [KSV012][ksv012] in trivy-checks. -You can get the package names in the [trivy-checks repository][trivy-checks] or the JSON output from Trivy. - -[ksv012]: https://github.com/aquasecurity/trivy-checks/blob/f36a5b732c4b1293a720c40baab0a7c106ea455e/checks/kubernetes/pss/restricted/3_runs_as_root.rego -[trivy-checks]: https://github.com/aquasecurity/trivy-checks/ \ No newline at end of file diff --git a/docs/docs/scanner/misconfiguration/custom/debug.md b/docs/docs/scanner/misconfiguration/custom/debug.md index 54ec9fd65273..bb7b506c7ece 100644 --- a/docs/docs/scanner/misconfiguration/custom/debug.md +++ b/docs/docs/scanner/misconfiguration/custom/debug.md @@ -12,7 +12,7 @@ $ trivy config --trace configs/ Dockerfile (dockerfile) ======================= -Tests: 23 (SUCCESSES: 21, FAILURES: 2, EXCEPTIONS: 0) +Tests: 23 (SUCCESSES: 21, FAILURES: 2) Failures: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 1, CRITICAL: 0) MEDIUM: Specify a tag in the 'FROM' statement for image 'alpine' diff --git a/docs/docs/scanner/misconfiguration/custom/index.md b/docs/docs/scanner/misconfiguration/custom/index.md index 9598089b8562..d45638f1533d 100644 --- a/docs/docs/scanner/misconfiguration/custom/index.md +++ b/docs/docs/scanner/misconfiguration/custom/index.md @@ -163,7 +163,7 @@ Some fields are displayed in scan results. k.yaml (kubernetes) ─────────────────── -Tests: 32 (SUCCESSES: 31, FAILURES: 1, EXCEPTIONS: 0) +Tests: 32 (SUCCESSES: 31, FAILURES: 1) Failures: 1 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 0, CRITICAL: 0) LOW: Found deployment 'my-deployment' but deployments are not allowed diff --git a/docs/docs/scanner/misconfiguration/index.md b/docs/docs/scanner/misconfiguration/index.md index 368b4522b433..8a2f331b6ab0 100644 --- a/docs/docs/scanner/misconfiguration/index.md +++ b/docs/docs/scanner/misconfiguration/index.md @@ -20,7 +20,7 @@ $ trivy config [YOUR_IaC_DIRECTORY] Dockerfile (dockerfile) ======================= - Tests: 23 (SUCCESSES: 22, FAILURES: 1, EXCEPTIONS: 0) + Tests: 23 (SUCCESSES: 22, FAILURES: 1) Failures: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0) MEDIUM: Specify a tag in the 'FROM' statement for image 'alpine' @@ -75,7 +75,7 @@ You can specify `--scanners vuln,misconfig,secret` to enable vulnerability and s Dockerfile (dockerfile) ======================= - Tests: 17 (SUCCESSES: 16, FAILURES: 1, EXCEPTIONS: 0) + Tests: 17 (SUCCESSES: 16, FAILURES: 1) Failures: 1 (HIGH: 1, CRITICAL: 0) HIGH: Last USER command in Dockerfile should not be 'root' @@ -112,7 +112,7 @@ $ trivy config --severity HIGH,CRITICAL ./iac Dockerfile (dockerfile) -Tests: 21 (SUCCESSES: 20, FAILURES: 1, EXCEPTIONS: 0) +Tests: 21 (SUCCESSES: 20, FAILURES: 1) Failures: 1 (MEDIUM: 0, HIGH: 1, CRITICAL: 0) HIGH: Specify at least 1 USER command in Dockerfile with non-root user as argument @@ -126,7 +126,7 @@ See https://avd.aquasec.com/misconfig/ds002 deployment.yaml (kubernetes) -Tests: 20 (SUCCESSES: 15, FAILURES: 5, EXCEPTIONS: 0) +Tests: 20 (SUCCESSES: 15, FAILURES: 5) Failures: 5 (MEDIUM: 4, HIGH: 1, CRITICAL: 0) MEDIUM: Container 'hello-kubernetes' of Deployment 'hello-kubernetes' should set 'securityContext.allowPrivilegeEscalation' to false @@ -225,7 +225,7 @@ See https://avd.aquasec.com/misconfig/ksv026 mysql-8.8.26.tar:templates/primary/statefulset.yaml (helm) -Tests: 20 (SUCCESSES: 18, FAILURES: 2, EXCEPTIONS: 0) +Tests: 20 (SUCCESSES: 18, FAILURES: 2) Failures: 2 (MEDIUM: 2, HIGH: 0, CRITICAL: 0) MEDIUM: Container 'mysql' of StatefulSet 'mysql' should set 'securityContext.allowPrivilegeEscalation' to false @@ -279,35 +279,35 @@ You can see the config type next to each file name. ``` bash Dockerfile (dockerfile) ======================= -Tests: 23 (SUCCESSES: 22, FAILURES: 1, EXCEPTIONS: 0) +Tests: 23 (SUCCESSES: 22, FAILURES: 1) Failures: 1 (HIGH: 1, CRITICAL: 0) ... deployment.yaml (kubernetes) ============================ -Tests: 28 (SUCCESSES: 15, FAILURES: 13, EXCEPTIONS: 0) +Tests: 28 (SUCCESSES: 15, FAILURES: 13) Failures: 13 (MEDIUM: 4, HIGH: 1, CRITICAL: 0) ... main.tf (terraform) =================== -Tests: 23 (SUCCESSES: 14, FAILURES: 9, EXCEPTIONS: 0) +Tests: 23 (SUCCESSES: 14, FAILURES: 9) Failures: 9 (HIGH: 6, CRITICAL: 1) ... bucket.yaml (cloudformation) ============================ -Tests: 9 (SUCCESSES: 3, FAILURES: 6, EXCEPTIONS: 0) +Tests: 9 (SUCCESSES: 3, FAILURES: 6) Failures: 6 (UNKNOWN: 0, LOW: 0, MEDIUM: 2, HIGH: 4, CRITICAL: 0) ... mysql-8.8.26.tar:templates/primary/statefulset.yaml (helm) ========================================================== -Tests: 20 (SUCCESSES: 18, FAILURES: 2, EXCEPTIONS: 0) +Tests: 20 (SUCCESSES: 18, FAILURES: 2) Failures: 2 (MEDIUM: 2, HIGH: 0, CRITICAL: 0) ``` @@ -381,7 +381,7 @@ deny[res] { $ trivy config --misconfig-scanners=json,yaml --config-check ./serverless.rego --check-namespaces user ./iac serverless.yaml (yaml) -Tests: 4 (SUCCESSES: 3, FAILURES: 1, EXCEPTIONS: 0) +Tests: 4 (SUCCESSES: 3, FAILURES: 1) Failures: 1 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 0, CRITICAL: 0) LOW: Service name "serverless-rest-api-with-pynamodb" is not allowed diff --git a/docs/docs/target/container_image.md b/docs/docs/target/container_image.md index f1c491071a3f..274b43862339 100644 --- a/docs/docs/target/container_image.md +++ b/docs/docs/target/container_image.md @@ -119,7 +119,7 @@ $ trivy image --image-config-scanners misconfig [YOUR_IMAGE_NAME] ``` alpine:3.17 (dockerfile) ======================== -Tests: 24 (SUCCESSES: 21, FAILURES: 3, EXCEPTIONS: 0) +Tests: 24 (SUCCESSES: 21, FAILURES: 3) Failures: 3 (UNKNOWN: 0, LOW: 2, MEDIUM: 0, HIGH: 1, CRITICAL: 0) HIGH: Specify at least 1 USER command in Dockerfile with non-root user as argument diff --git a/docs/docs/target/kubernetes.md b/docs/docs/target/kubernetes.md index 10253aff4c72..291c9fb7728e 100644 --- a/docs/docs/target/kubernetes.md +++ b/docs/docs/target/kubernetes.md @@ -280,8 +280,7 @@ trivy k8s --format json -o results.json cluster "Type": "kubernetes", "MisconfSummary": { "Successes": 20, - "Failures": 19, - "Exceptions": 0 + "Failures": 19 }, "Misconfigurations": [ { diff --git a/integration/repo_test.go b/integration/repo_test.go index 69833bcf2b77..6b4e3a338457 100644 --- a/integration/repo_test.go +++ b/integration/repo_test.go @@ -309,15 +309,6 @@ func TestRepository(t *testing.T) { }, golden: "testdata/dockerfile-rule-exception.json.golden", }, - { - name: "dockerfile with namespace exception", - args: args{ - scanner: types.MisconfigScanner, - policyPaths: []string{"testdata/fixtures/repo/namespace-exception/policy"}, - input: "testdata/fixtures/repo/namespace-exception", - }, - golden: "testdata/dockerfile-namespace-exception.json.golden", - }, { name: "dockerfile with custom policies", args: args{ diff --git a/integration/testdata/dockerfile-custom-policies.json.golden b/integration/testdata/dockerfile-custom-policies.json.golden index 438ecf5d7270..2cbda6f16703 100644 --- a/integration/testdata/dockerfile-custom-policies.json.golden +++ b/integration/testdata/dockerfile-custom-policies.json.golden @@ -22,8 +22,7 @@ "Type": "dockerfile", "MisconfSummary": { "Successes": 27, - "Failures": 2, - "Exceptions": 0 + "Failures": 2 }, "Misconfigurations": [ { diff --git a/integration/testdata/dockerfile-namespace-exception.json.golden b/integration/testdata/dockerfile-namespace-exception.json.golden deleted file mode 100644 index be3a6adfa8d6..000000000000 --- a/integration/testdata/dockerfile-namespace-exception.json.golden +++ /dev/null @@ -1,30 +0,0 @@ -{ - "SchemaVersion": 2, - "CreatedAt": "2021-08-25T12:20:30.000000005Z", - "ArtifactName": "testdata/fixtures/repo/namespace-exception", - "ArtifactType": "repository", - "Metadata": { - "ImageConfig": { - "architecture": "", - "created": "0001-01-01T00:00:00Z", - "os": "", - "rootfs": { - "type": "", - "diff_ids": null - }, - "config": {} - } - }, - "Results": [ - { - "Target": "Dockerfile", - "Class": "config", - "Type": "dockerfile", - "MisconfSummary": { - "Successes": 0, - "Failures": 0, - "Exceptions": 27 - } - } - ] -} diff --git a/integration/testdata/dockerfile-rule-exception.json.golden b/integration/testdata/dockerfile-rule-exception.json.golden index eae4e1e32fd6..eedcb902e145 100644 --- a/integration/testdata/dockerfile-rule-exception.json.golden +++ b/integration/testdata/dockerfile-rule-exception.json.golden @@ -22,8 +22,7 @@ "Type": "dockerfile", "MisconfSummary": { "Successes": 26, - "Failures": 1, - "Exceptions": 0 + "Failures": 1 }, "Misconfigurations": [ { diff --git a/integration/testdata/dockerfile.json.golden b/integration/testdata/dockerfile.json.golden index 3f6dd1b5b201..834b110404c1 100644 --- a/integration/testdata/dockerfile.json.golden +++ b/integration/testdata/dockerfile.json.golden @@ -22,8 +22,7 @@ "Type": "dockerfile", "MisconfSummary": { "Successes": 26, - "Failures": 1, - "Exceptions": 0 + "Failures": 1 }, "Misconfigurations": [ { diff --git a/integration/testdata/dockerfile_file_pattern.json.golden b/integration/testdata/dockerfile_file_pattern.json.golden index fe0372ddc79c..ed917023bc4b 100644 --- a/integration/testdata/dockerfile_file_pattern.json.golden +++ b/integration/testdata/dockerfile_file_pattern.json.golden @@ -22,8 +22,7 @@ "Type": "dockerfile", "MisconfSummary": { "Successes": 26, - "Failures": 1, - "Exceptions": 0 + "Failures": 1 }, "Misconfigurations": [ { diff --git a/integration/testdata/fixtures/repo/namespace-exception/Dockerfile b/integration/testdata/fixtures/repo/namespace-exception/Dockerfile deleted file mode 100644 index fa4b7580b688..000000000000 --- a/integration/testdata/fixtures/repo/namespace-exception/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM alpine:3.13 -LABEL user.root="allow" diff --git a/integration/testdata/fixtures/repo/namespace-exception/policy/exception.rego b/integration/testdata/fixtures/repo/namespace-exception/policy/exception.rego deleted file mode 100644 index 74abdccb1933..000000000000 --- a/integration/testdata/fixtures/repo/namespace-exception/policy/exception.rego +++ /dev/null @@ -1,8 +0,0 @@ -package namespace.exceptions - -import data.namespaces - -exception[ns] { - ns := data.namespaces[_] - startswith(ns, "builtin") -} \ No newline at end of file diff --git a/integration/testdata/helm.json.golden b/integration/testdata/helm.json.golden index 518458ac1088..8b9ccb11bc9c 100644 --- a/integration/testdata/helm.json.golden +++ b/integration/testdata/helm.json.golden @@ -22,8 +22,7 @@ "Type": "helm", "MisconfSummary": { "Successes": 80, - "Failures": 14, - "Exceptions": 0 + "Failures": 14 }, "Misconfigurations": [ { diff --git a/integration/testdata/helm_testchart.json.golden b/integration/testdata/helm_testchart.json.golden index 2e659b13e68a..886b0a702496 100644 --- a/integration/testdata/helm_testchart.json.golden +++ b/integration/testdata/helm_testchart.json.golden @@ -22,8 +22,7 @@ "Type": "helm", "MisconfSummary": { "Successes": 90, - "Failures": 4, - "Exceptions": 0 + "Failures": 4 }, "Misconfigurations": [ { @@ -342,8 +341,7 @@ "Type": "helm", "MisconfSummary": { "Successes": 61, - "Failures": 0, - "Exceptions": 0 + "Failures": 0 } }, { @@ -352,8 +350,7 @@ "Type": "helm", "MisconfSummary": { "Successes": 60, - "Failures": 0, - "Exceptions": 0 + "Failures": 0 } } ] diff --git a/integration/testdata/helm_testchart.overridden.json.golden b/integration/testdata/helm_testchart.overridden.json.golden index f4c984daa458..354cb3cbf786 100644 --- a/integration/testdata/helm_testchart.overridden.json.golden +++ b/integration/testdata/helm_testchart.overridden.json.golden @@ -22,8 +22,7 @@ "Type": "helm", "MisconfSummary": { "Successes": 88, - "Failures": 6, - "Exceptions": 0 + "Failures": 6 }, "Misconfigurations": [ { @@ -569,8 +568,7 @@ "Type": "helm", "MisconfSummary": { "Successes": 61, - "Failures": 0, - "Exceptions": 0 + "Failures": 0 } }, { @@ -579,8 +577,7 @@ "Type": "helm", "MisconfSummary": { "Successes": 60, - "Failures": 0, - "Exceptions": 0 + "Failures": 0 } } ] diff --git a/mkdocs.yml b/mkdocs.yml index 00e458e15a91..ab3d51b71275 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -56,7 +56,6 @@ nav: - Overview: docs/scanner/misconfiguration/index.md - Policy: - Built-in Checks: docs/scanner/misconfiguration/check/builtin.md - - Exceptions: docs/scanner/misconfiguration/check/exceptions.md - Custom Checks: - Overview: docs/scanner/misconfiguration/custom/index.md - Data: docs/scanner/misconfiguration/custom/data.md diff --git a/pkg/cache/mock_artifact_cache.go b/pkg/cache/mock_artifact_cache.go index e0b1430337e4..ef9503203a7f 100644 --- a/pkg/cache/mock_artifact_cache.go +++ b/pkg/cache/mock_artifact_cache.go @@ -229,9 +229,6 @@ func (_m *MockArtifactCache) PutBlob(blobID string, blobInfo types.BlobInfo) err for j := range blobInfo.Misconfigurations[i].Warnings { blobInfo.Misconfigurations[i].Warnings[j].Code = types.Code{} } - for j := range blobInfo.Misconfigurations[i].Exceptions { - blobInfo.Misconfigurations[i].Exceptions[j].Code = types.Code{} - } } ret := _m.Called(blobID, blobInfo) diff --git a/pkg/compliance/report/report_test.go b/pkg/compliance/report/report_test.go index e673bd50a24d..5481299b57ea 100644 --- a/pkg/compliance/report/report_test.go +++ b/pkg/compliance/report/report_test.go @@ -36,9 +36,8 @@ func TestBuildComplianceReport(t *testing.T) { Class: types.ClassConfig, Type: ftypes.Kubernetes, MisconfSummary: &types.MisconfSummary{ - Successes: 1, - Failures: 0, - Exceptions: 0, + Successes: 1, + Failures: 0, }, Misconfigurations: []types.DetectedMisconfiguration{ { @@ -158,9 +157,8 @@ func TestBuildComplianceReport(t *testing.T) { Class: types.ClassConfig, Type: ftypes.Kubernetes, MisconfSummary: &types.MisconfSummary{ - Successes: 1, - Failures: 0, - Exceptions: 0, + Successes: 1, + Failures: 0, }, Misconfigurations: []types.DetectedMisconfiguration{ { diff --git a/pkg/compliance/report/testdata/table_all.txt b/pkg/compliance/report/testdata/table_all.txt index 8a789b2ceaa5..159d5f8590ad 100644 --- a/pkg/compliance/report/testdata/table_all.txt +++ b/pkg/compliance/report/testdata/table_all.txt @@ -1,9 +1,9 @@ - -Deployment/metrics-server (kubernetes) -====================================== -Tests: 1 (SUCCESSES: 1, FAILURES: 0, EXCEPTIONS: 0) -Failures: 0 () - + +Deployment/metrics-server (kubernetes) +====================================== +Tests: 1 (SUCCESSES: 1, FAILURES: 0) +Failures: 0 () + MEDIUM: Container 'metrics-server' of Deployment 'metrics-server' should set 'securityContext.allowPrivilegeEscalation' to false ════════════════════════════════════════ A program inside the container can elevate its own privileges and run as root, which might give the program control over the container and node. @@ -24,12 +24,12 @@ See https://avd.aquasec.com/misconfig/ksv001 ──────────────────────────────────────── - -Deployment/metrics-server (kubernetes) -====================================== -Tests: 1 (SUCCESSES: 1, FAILURES: 0, EXCEPTIONS: 0) -Failures: 0 () - + +Deployment/metrics-server (kubernetes) +====================================== +Tests: 1 (SUCCESSES: 1, FAILURES: 0) +Failures: 0 () + LOW: Container 'metrics-server' of Deployment 'metrics-server' should add 'ALL' to 'securityContext.capabilities.drop' ════════════════════════════════════════ The container should drop all default capabilities and add only those that are needed for its execution. diff --git a/pkg/compliance/spec/mapper.go b/pkg/compliance/spec/mapper.go index 6fa5d2bbd45a..8c683753ad90 100644 --- a/pkg/compliance/spec/mapper.go +++ b/pkg/compliance/spec/mapper.go @@ -49,8 +49,6 @@ func misconfigSummary(misconfig types.DetectedMisconfiguration) *types.MisconfSu rms.Successes = 1 case types.MisconfStatusFailure: rms.Failures = 1 - case types.MisconfStatusException: - rms.Exceptions = 1 } return &rms } diff --git a/pkg/compliance/spec/mapper_test.go b/pkg/compliance/spec/mapper_test.go index 62050d27ec47..070c06a8ce96 100644 --- a/pkg/compliance/spec/mapper_test.go +++ b/pkg/compliance/spec/mapper_test.go @@ -61,9 +61,8 @@ func TestMapSpecCheckIDToFilteredResults(t *testing.T) { Class: types.ClassConfig, Type: ftypes.Kubernetes, MisconfSummary: &types.MisconfSummary{ - Successes: 0, - Failures: 1, - Exceptions: 0, + Successes: 0, + Failures: 1, }, Misconfigurations: []types.DetectedMisconfiguration{ { @@ -79,9 +78,8 @@ func TestMapSpecCheckIDToFilteredResults(t *testing.T) { Class: types.ClassConfig, Type: ftypes.Kubernetes, MisconfSummary: &types.MisconfSummary{ - Successes: 0, - Failures: 1, - Exceptions: 0, + Successes: 0, + Failures: 1, }, Misconfigurations: []types.DetectedMisconfiguration{ { diff --git a/pkg/fanal/types/misconf.go b/pkg/fanal/types/misconf.go index 3b4e9b447895..706220f0a1c7 100644 --- a/pkg/fanal/types/misconf.go +++ b/pkg/fanal/types/misconf.go @@ -8,13 +8,12 @@ import ( ) type Misconfiguration struct { - FileType ConfigType `json:",omitempty"` - FilePath string `json:",omitempty"` - Successes MisconfResults `json:",omitempty"` - Warnings MisconfResults `json:",omitempty"` - Failures MisconfResults `json:",omitempty"` - Exceptions MisconfResults `json:",omitempty"` - Layer Layer `json:",omitempty"` + FileType ConfigType `json:",omitempty"` + FilePath string `json:",omitempty"` + Successes MisconfResults `json:",omitempty"` + Warnings MisconfResults `json:",omitempty"` + Failures MisconfResults `json:",omitempty"` + Layer Layer `json:",omitempty"` } type MisconfResult struct { @@ -117,7 +116,6 @@ func ToMisconfigurations(misconfs map[string]Misconfiguration) []Misconfiguratio sort.Sort(misconf.Successes) sort.Sort(misconf.Warnings) sort.Sort(misconf.Failures) - sort.Sort(misconf.Exceptions) results = append(results, misconf) } diff --git a/pkg/flag/misconf_flags.go b/pkg/flag/misconf_flags.go index 128ecfcac42e..421e9c899285 100644 --- a/pkg/flag/misconf_flags.go +++ b/pkg/flag/misconf_flags.go @@ -34,7 +34,7 @@ var ( IncludeNonFailuresFlag = Flag[bool]{ Name: "include-non-failures", ConfigName: "misconfiguration.include-non-failures", - Usage: "include successes and exceptions, available with '--scanners misconfig'", + Usage: "include successes, available with '--scanners misconfig'", } HelmValuesFileFlag = Flag[[]string]{ Name: "helm-values", diff --git a/pkg/iac/rego/exceptions.go b/pkg/iac/rego/exceptions.go deleted file mode 100644 index 591c72abdbbb..000000000000 --- a/pkg/iac/rego/exceptions.go +++ /dev/null @@ -1,35 +0,0 @@ -package rego - -import ( - "context" - "fmt" - - "github.com/open-policy-agent/opa/ast" -) - -func (s *Scanner) isIgnored(ctx context.Context, namespace, ruleName string, input ast.Value) (bool, error) { - if ignored, err := s.isNamespaceIgnored(ctx, namespace, input); err != nil { - return false, err - } else if ignored { - return true, nil - } - return s.isRuleIgnored(ctx, namespace, ruleName, input) -} - -func (s *Scanner) isNamespaceIgnored(ctx context.Context, namespace string, input ast.Value) (bool, error) { - exceptionQuery := fmt.Sprintf("data.namespace.exceptions.exception[_] == %q", namespace) - result, _, err := s.runQuery(ctx, exceptionQuery, input, true) - if err != nil { - return false, fmt.Errorf("query namespace exceptions: %w", err) - } - return result.Allowed(), nil -} - -func (s *Scanner) isRuleIgnored(ctx context.Context, namespace, ruleName string, input ast.Value) (bool, error) { - exceptionQuery := fmt.Sprintf("endswith(%q, data.%s.exception[_][_])", ruleName, namespace) - result, _, err := s.runQuery(ctx, exceptionQuery, input, true) - if err != nil { - return false, err - } - return result.Allowed(), nil -} diff --git a/pkg/iac/rego/scanner.go b/pkg/iac/rego/scanner.go index 9cf80fc83da0..f791a45bf74d 100644 --- a/pkg/iac/rego/scanner.go +++ b/pkg/iac/rego/scanner.go @@ -345,16 +345,7 @@ func (s *Scanner) applyRule(ctx context.Context, namespace, rule string, inputs s.logger.Error("Error occurred while parsing input", log.Err(err)) continue } - if ignored, err := s.isIgnored(ctx, namespace, rule, parsedInput); err != nil { - return nil, err - } else if ignored { - var result regoResult - result.FS = input.FS - result.Filepath = input.Path - result.Managed = true - results.AddIgnored(result) - continue - } + set, traces, err := s.runQuery(ctx, qualified, parsedInput, false) if err != nil { return nil, err @@ -385,20 +376,6 @@ func (s *Scanner) applyRuleCombined(ctx context.Context, namespace, rule string, return nil, fmt.Errorf("failed to parse input: %w", err) } - var results scan.Results - - if ignored, err := s.isIgnored(ctx, namespace, rule, parsed); err != nil { - return nil, err - } else if ignored { - for _, input := range inputs { - var result regoResult - result.FS = input.FS - result.Filepath = input.Path - result.Managed = true - results.AddIgnored(result) - } - return results, nil - } qualified := fmt.Sprintf("data.%s.%s", namespace, rule) set, traces, err := s.runQuery(ctx, qualified, parsed, false) if err != nil { diff --git a/pkg/iac/rego/scanner_test.go b/pkg/iac/rego/scanner_test.go index 1310e56d2ec4..880bc9c1f9f9 100644 --- a/pkg/iac/rego/scanner_test.go +++ b/pkg/iac/rego/scanner_test.go @@ -166,168 +166,6 @@ deny { assert.Equal(t, "/evil.lol", results.GetPassed()[0].Metadata().Range().GetFilename()) } -func Test_RegoScanning_Namespace_Exception(t *testing.T) { - - srcFS := CreateFS(t, map[string]string{ - "policies/test.rego": ` -package defsec.test - -deny { - input.evil -} -`, - "policies/exceptions.rego": ` -package namespace.exceptions - -import data.namespaces - -exception[ns] { - ns := data.namespaces[_] - startswith(ns, "defsec") -} -`, - }) - - scanner := rego.NewScanner( - types.SourceJSON, - rego.WithPolicyDirs("policies"), - ) - require.NoError(t, scanner.LoadPolicies(srcFS)) - - results, err := scanner.ScanInput(context.TODO(), rego.Input{ - Path: "/evil.lol", - Contents: map[string]any{ - "evil": true, - }, - }) - require.NoError(t, err) - - assert.Empty(t, results.GetFailed()) - assert.Empty(t, results.GetPassed()) - assert.Len(t, results.GetIgnored(), 1) - -} - -func Test_RegoScanning_Namespace_Exception_WithoutMatch(t *testing.T) { - - srcFS := CreateFS(t, map[string]string{ - "policies/test.rego": ` -package defsec.test - -deny { - input.evil -} -`, "policies/something.rego": ` -package builtin.test - -deny_something { - input.something -} -`, - "policies/exceptions.rego": ` -package namespace.exceptions - -import data.namespaces - -exception[ns] { - ns := data.namespaces[_] - startswith(ns, "builtin") -} -`, - }) - - scanner := rego.NewScanner( - types.SourceJSON, - rego.WithPolicyDirs("policies"), - ) - require.NoError(t, scanner.LoadPolicies(srcFS)) - - results, err := scanner.ScanInput(context.TODO(), rego.Input{ - Path: "/evil.lol", - Contents: map[string]any{ - "evil": true, - }, - }) - require.NoError(t, err) - - assert.Len(t, results.GetFailed(), 1) - assert.Empty(t, results.GetPassed()) - assert.Len(t, results.GetIgnored(), 1) - -} - -func Test_RegoScanning_Rule_Exception(t *testing.T) { - srcFS := CreateFS(t, map[string]string{ - "policies/test.rego": ` -package defsec.test -deny_evil { - input.evil -} -`, - "policies/exceptions.rego": ` -package defsec.test - -exception[rules] { - rules := ["evil"] -} -`, - }) - - scanner := rego.NewScanner( - types.SourceJSON, - rego.WithPolicyDirs("policies"), - ) - require.NoError(t, scanner.LoadPolicies(srcFS)) - - results, err := scanner.ScanInput(context.TODO(), rego.Input{ - Path: "/evil.lol", - Contents: map[string]any{ - "evil": true, - }, - }) - require.NoError(t, err) - - assert.Empty(t, results.GetFailed()) - assert.Empty(t, results.GetPassed()) - assert.Len(t, results.GetIgnored(), 1) -} - -func Test_RegoScanning_Rule_Exception_WithoutMatch(t *testing.T) { - srcFS := CreateFS(t, map[string]string{ - "policies/test.rego": ` -package defsec.test -deny_evil { - input.evil -} -`, - "policies/exceptions.rego": ` -package defsec.test - -exception[rules] { - rules := ["good"] -} -`, - }) - - scanner := rego.NewScanner( - types.SourceJSON, - rego.WithPolicyDirs("policies"), - ) - require.NoError(t, scanner.LoadPolicies(srcFS)) - - results, err := scanner.ScanInput(context.TODO(), rego.Input{ - Path: "/evil.lol", - Contents: map[string]any{ - "evil": true, - }, - }) - require.NoError(t, err) - - assert.Len(t, results.GetFailed(), 1) - assert.Empty(t, results.GetPassed()) - assert.Empty(t, results.GetIgnored()) -} - func Test_RegoScanning_WithRuntimeValues(t *testing.T) { t.Setenv("DEFSEC_RUNTIME_VAL", "AOK") diff --git a/pkg/iac/scanners/cloudformation/scanner.go b/pkg/iac/scanners/cloudformation/scanner.go index 4497a807506c..0e3fec472b96 100644 --- a/pkg/iac/scanners/cloudformation/scanner.go +++ b/pkg/iac/scanners/cloudformation/scanner.go @@ -205,6 +205,7 @@ func (s *Scanner) scanFileContext(ctx context.Context, regoScanner *rego.Scanner } results = append(results, regoResults...) + // ignore a result based on user input results.Ignore(cfCtx.Ignores, nil) for _, ignored := range results.GetIgnored() { diff --git a/pkg/iac/scanners/terraform/executor/executor.go b/pkg/iac/scanners/terraform/executor/executor.go index 452e47dcc8de..8e14f778e5b4 100644 --- a/pkg/iac/scanners/terraform/executor/executor.go +++ b/pkg/iac/scanners/terraform/executor/executor.go @@ -85,6 +85,7 @@ func (e *Executor) Execute(modules terraform.Modules) (scan.Results, error) { "ignore": attributeIgnorer(modules), } + // ignore a result based on user input results.Ignore(ignores, ignorers) for _, ignored := range results.GetIgnored() { diff --git a/pkg/misconf/scanner.go b/pkg/misconf/scanner.go index 7a3642dfe895..1aa2a5cd5c16 100644 --- a/pkg/misconf/scanner.go +++ b/pkg/misconf/scanner.go @@ -488,8 +488,6 @@ func ResultsToMisconf(configType types.ConfigType, scannerName string, results s switch flattened.Status { case scan.StatusPassed: misconf.Successes = append(misconf.Successes, misconfResult) - case scan.StatusIgnored: - misconf.Exceptions = append(misconf.Exceptions, misconfResult) case scan.StatusFailed: misconf.Failures = append(misconf.Failures, misconfResult) } diff --git a/pkg/report/table/misconfig.go b/pkg/report/table/misconfig.go index dfb724bdf458..41f111d883c9 100644 --- a/pkg/report/table/misconfig.go +++ b/pkg/report/table/misconfig.go @@ -61,8 +61,8 @@ func (r *misconfigRenderer) Render() string { total, summaries := summarize(r.severities, r.countSeverities()) summary := r.result.MisconfSummary - r.printf("Tests: %d (SUCCESSES: %d, FAILURES: %d, EXCEPTIONS: %d)\n", - summary.Successes+summary.Failures+summary.Exceptions, summary.Successes, summary.Failures, summary.Exceptions) + r.printf("Tests: %d (SUCCESSES: %d, FAILURES: %d)\n", + summary.Successes+summary.Failures, summary.Successes, summary.Failures) r.printf("Failures: %d (%s)\n\n", total, strings.Join(summaries, ", ")) for _, m := range r.result.Misconfigurations { diff --git a/pkg/report/table/misconfig_test.go b/pkg/report/table/misconfig_test.go index 785b2621b504..8d17798f673d 100644 --- a/pkg/report/table/misconfig_test.go +++ b/pkg/report/table/misconfig_test.go @@ -24,7 +24,7 @@ func TestMisconfigRenderer(t *testing.T) { name: "single result", input: types.Result{ Target: "my-file", - MisconfSummary: &types.MisconfSummary{Successes: 0, Failures: 1, Exceptions: 0}, + MisconfSummary: &types.MisconfSummary{Successes: 0, Failures: 1}, Misconfigurations: []types.DetectedMisconfiguration{ { ID: "some-alias-for-a-check", @@ -42,7 +42,7 @@ func TestMisconfigRenderer(t *testing.T) { want: ` my-file () ========== -Tests: 1 (SUCCESSES: 0, FAILURES: 1, EXCEPTIONS: 0) +Tests: 1 (SUCCESSES: 0, FAILURES: 1) Failures: 1 (LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 0) AVD-XYZ-0123 (HIGH): Oh no, a bad config. @@ -59,7 +59,7 @@ See https://google.com/search?q=bad%20config name: "single result with code", input: types.Result{ Target: "my-file", - MisconfSummary: &types.MisconfSummary{Successes: 0, Failures: 1, Exceptions: 0}, + MisconfSummary: &types.MisconfSummary{Successes: 0, Failures: 1}, Misconfigurations: []types.DetectedMisconfiguration{ { AVDID: "AVD-XYZ-0123", @@ -101,7 +101,7 @@ See https://google.com/search?q=bad%20config want: ` my-file () ========== -Tests: 1 (SUCCESSES: 0, FAILURES: 1, EXCEPTIONS: 0) +Tests: 1 (SUCCESSES: 0, FAILURES: 1) Failures: 1 (LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 0) AVD-XYZ-0123 (HIGH): Oh no, a bad config. @@ -124,7 +124,7 @@ See https://google.com/search?q=bad%20config name: "multiple results", input: types.Result{ Target: "my-file", - MisconfSummary: &types.MisconfSummary{Successes: 1, Failures: 1, Exceptions: 0}, + MisconfSummary: &types.MisconfSummary{Successes: 1, Failures: 1}, Misconfigurations: []types.DetectedMisconfiguration{ { AVDID: "AVD-XYZ-0123", @@ -172,7 +172,7 @@ See https://google.com/search?q=bad%20config want: ` my-file () ========== -Tests: 2 (SUCCESSES: 1, FAILURES: 1, EXCEPTIONS: 0) +Tests: 2 (SUCCESSES: 1, FAILURES: 1) Failures: 1 (LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 0) FAIL: AVD-XYZ-0123 (HIGH): Oh no, a bad config. @@ -206,9 +206,8 @@ See https://google.com/search?q=bad%20config Class: types.ClassConfig, Type: "terraform", MisconfSummary: &types.MisconfSummary{ - Successes: 5, - Failures: 1, - Exceptions: 0, + Successes: 5, + Failures: 1, }, Misconfigurations: []types.DetectedMisconfiguration{ { @@ -310,7 +309,7 @@ See https://google.com/search?q=bad%20config want: ` terraform-aws-modules/security-group/aws/main.tf (terraform) ============================================================ -Tests: 6 (SUCCESSES: 5, FAILURES: 1, EXCEPTIONS: 0) +Tests: 6 (SUCCESSES: 5, FAILURES: 1) Failures: 1 (LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 1) AVD-AWS-0107 (CRITICAL): Security group rule allows ingress from public internet. diff --git a/pkg/result/filter.go b/pkg/result/filter.go index e1f0e632197e..83e0c0a7170e 100644 --- a/pkg/result/filter.go +++ b/pkg/result/filter.go @@ -130,13 +130,12 @@ func filterMisconfigurations(result *types.Result, severities []string, includeN // Filter by ignore file if f := ignoreConfig.MatchMisconfiguration(misconf.ID, misconf.AVDID, result.Target); f != nil { - result.MisconfSummary.Exceptions++ result.ModifiedFindings = append(result.ModifiedFindings, types.NewModifiedFinding(misconf, types.FindingStatusIgnored, f.Statement, ignoreConfig.FilePath)) continue } - // Count successes, failures, and exceptions + // Count successes and failures summarize(misconf.Status, result.MisconfSummary) if misconf.Status != types.MisconfStatusFailure && !includeNonFailures { @@ -210,8 +209,6 @@ func summarize(status types.MisconfStatus, summary *types.MisconfSummary) { summary.Failures++ case types.MisconfStatusPassed: summary.Successes++ - case types.MisconfStatusException: - summary.Exceptions++ } } @@ -256,7 +253,6 @@ func applyPolicy(ctx context.Context, result *types.Result, policyFile string) e return err } if ignored { - result.MisconfSummary.Exceptions++ switch misconf.Status { case types.MisconfStatusFailure: result.MisconfSummary.Failures-- diff --git a/pkg/result/filter_test.go b/pkg/result/filter_test.go index 0298cd0d9582..289ec2ee0c63 100644 --- a/pkg/result/filter_test.go +++ b/pkg/result/filter_test.go @@ -233,9 +233,8 @@ func TestFilter(t *testing.T) { vuln2, }, MisconfSummary: &types.MisconfSummary{ - Successes: 0, - Failures: 1, - Exceptions: 0, + Successes: 0, + Failures: 1, }, Misconfigurations: []types.DetectedMisconfiguration{ misconf1, @@ -403,9 +402,8 @@ func TestFilter(t *testing.T) { Target: "deployment.yaml", Class: types.ClassConfig, MisconfSummary: &types.MisconfSummary{ - Successes: 1, - Failures: 1, - Exceptions: 1, + Successes: 1, + Failures: 1, }, Misconfigurations: []types.DetectedMisconfiguration{ misconf1, @@ -522,9 +520,8 @@ func TestFilter(t *testing.T) { { Target: "app/Dockerfile", MisconfSummary: &types.MisconfSummary{ - Successes: 0, - Failures: 1, - Exceptions: 2, + Successes: 0, + Failures: 1, }, Misconfigurations: []types.DetectedMisconfiguration{ misconf3, @@ -641,9 +638,8 @@ func TestFilter(t *testing.T) { Results: types.Results{ { MisconfSummary: &types.MisconfSummary{ - Successes: 1, - Failures: 1, - Exceptions: 1, + Successes: 1, + Failures: 1, }, Misconfigurations: []types.DetectedMisconfiguration{ misconf1, diff --git a/pkg/rpc/convert.go b/pkg/rpc/convert.go index 1662877bd597..89097730111b 100644 --- a/pkg/rpc/convert.go +++ b/pkg/rpc/convert.go @@ -754,13 +754,12 @@ func ConvertFromRPCMisconfigurations(rpcMisconfs []*common.Misconfiguration) []f var misconfs []ftypes.Misconfiguration for _, rpcMisconf := range rpcMisconfs { misconfs = append(misconfs, ftypes.Misconfiguration{ - FileType: ftypes.ConfigType(rpcMisconf.FileType), - FilePath: rpcMisconf.FilePath, - Successes: ConvertFromRPCMisconfResults(rpcMisconf.Successes), - Warnings: ConvertFromRPCMisconfResults(rpcMisconf.Warnings), - Failures: ConvertFromRPCMisconfResults(rpcMisconf.Failures), - Exceptions: ConvertFromRPCMisconfResults(rpcMisconf.Exceptions), - Layer: ftypes.Layer{}, + FileType: ftypes.ConfigType(rpcMisconf.FileType), + FilePath: rpcMisconf.FilePath, + Successes: ConvertFromRPCMisconfResults(rpcMisconf.Successes), + Warnings: ConvertFromRPCMisconfResults(rpcMisconf.Warnings), + Failures: ConvertFromRPCMisconfResults(rpcMisconf.Failures), + Layer: ftypes.Layer{}, }) } return misconfs @@ -875,12 +874,11 @@ func ConvertToRPCPutBlobRequest(diffID string, blobInfo ftypes.BlobInfo) *cache. var misconfigurations []*common.Misconfiguration for _, m := range blobInfo.Misconfigurations { misconfigurations = append(misconfigurations, &common.Misconfiguration{ - FileType: string(m.FileType), - FilePath: m.FilePath, - Successes: ConvertToMisconfResults(m.Successes), - Warnings: ConvertToMisconfResults(m.Warnings), - Failures: ConvertToMisconfResults(m.Failures), - Exceptions: ConvertToMisconfResults(m.Exceptions), + FileType: string(m.FileType), + FilePath: m.FilePath, + Successes: ConvertToMisconfResults(m.Successes), + Warnings: ConvertToMisconfResults(m.Warnings), + Failures: ConvertToMisconfResults(m.Failures), }) } diff --git a/pkg/scanner/local/scan.go b/pkg/scanner/local/scan.go index f34723058e06..58cd4cc00167 100644 --- a/pkg/scanner/local/scan.go +++ b/pkg/scanner/local/scan.go @@ -210,9 +210,6 @@ func (s Scanner) MisconfsToResults(misconfs []ftypes.Misconfiguration) types.Res for _, w := range misconf.Successes { detected = append(detected, toDetectedMisconfiguration(w, dbTypes.SeverityUnknown, types.MisconfStatusPassed, misconf.Layer)) } - for _, w := range misconf.Exceptions { - detected = append(detected, toDetectedMisconfiguration(w, dbTypes.SeverityUnknown, types.MisconfStatusException, misconf.Layer)) - } results = append(results, types.Result{ Target: misconf.FilePath, diff --git a/pkg/scanner/local/scan_test.go b/pkg/scanner/local/scan_test.go index f3e6cac5d3fa..bdeb5166a2fa 100644 --- a/pkg/scanner/local/scan_test.go +++ b/pkg/scanner/local/scan_test.go @@ -820,17 +820,6 @@ func TestScanner_Scan(t *testing.T) { }, }, }, - Exceptions: ftypes.MisconfResults{ - { - Namespace: "main.kubernetes.id100", - PolicyMetadata: ftypes.PolicyMetadata{ - ID: "ID100", - Type: "Kubernetes Security Check", - Title: "Bad Deployment", - Severity: "HIGH", - }, - }, - }, Layer: ftypes.Layer{ DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303", }, @@ -922,18 +911,6 @@ func TestScanner_Scan(t *testing.T) { DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303", }, }, - { - Type: "Kubernetes Security Check", - ID: "ID100", - Title: "Bad Deployment", - Message: "No issues found", - Namespace: "main.kubernetes.id100", - Severity: "HIGH", - Status: types.MisconfStatusException, - Layer: ftypes.Layer{ - DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303", - }, - }, }, }, }, diff --git a/pkg/types/report.go b/pkg/types/report.go index af364c95a11d..3ada68a942d8 100644 --- a/pkg/types/report.go +++ b/pkg/types/report.go @@ -130,13 +130,12 @@ func (r *Result) IsEmpty() bool { } type MisconfSummary struct { - Successes int - Failures int - Exceptions int + Successes int + Failures int } func (s MisconfSummary) Empty() bool { - return s.Successes == 0 && s.Failures == 0 && s.Exceptions == 0 + return s.Successes == 0 && s.Failures == 0 } // Failed returns whether the result includes any vulnerabilities, misconfigurations or secrets diff --git a/rpc/cache/service.pb.go b/rpc/cache/service.pb.go index d3a1fa1a63b9..acca9623e93a 100644 --- a/rpc/cache/service.pb.go +++ b/rpc/cache/service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 +// protoc-gen-go v1.34.0 // protoc v3.19.4 // source: rpc/cache/service.proto diff --git a/rpc/common/service.pb.go b/rpc/common/service.pb.go index 4c7f0af79464..c8290cc52818 100644 --- a/rpc/common/service.pb.go +++ b/rpc/common/service.pb.go @@ -755,12 +755,11 @@ type Misconfiguration struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - FileType string `protobuf:"bytes,1,opt,name=file_type,json=fileType,proto3" json:"file_type,omitempty"` - FilePath string `protobuf:"bytes,2,opt,name=file_path,json=filePath,proto3" json:"file_path,omitempty"` - Successes []*MisconfResult `protobuf:"bytes,3,rep,name=successes,proto3" json:"successes,omitempty"` - Warnings []*MisconfResult `protobuf:"bytes,4,rep,name=warnings,proto3" json:"warnings,omitempty"` - Failures []*MisconfResult `protobuf:"bytes,5,rep,name=failures,proto3" json:"failures,omitempty"` - Exceptions []*MisconfResult `protobuf:"bytes,6,rep,name=exceptions,proto3" json:"exceptions,omitempty"` + FileType string `protobuf:"bytes,1,opt,name=file_type,json=fileType,proto3" json:"file_type,omitempty"` + FilePath string `protobuf:"bytes,2,opt,name=file_path,json=filePath,proto3" json:"file_path,omitempty"` + Successes []*MisconfResult `protobuf:"bytes,3,rep,name=successes,proto3" json:"successes,omitempty"` + Warnings []*MisconfResult `protobuf:"bytes,4,rep,name=warnings,proto3" json:"warnings,omitempty"` + Failures []*MisconfResult `protobuf:"bytes,5,rep,name=failures,proto3" json:"failures,omitempty"` } func (x *Misconfiguration) Reset() { @@ -830,13 +829,6 @@ func (x *Misconfiguration) GetFailures() []*MisconfResult { return nil } -func (x *Misconfiguration) GetExceptions() []*MisconfResult { - if x != nil { - return x.Exceptions - } - return nil -} - type MisconfResult struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2482,7 +2474,7 @@ var file_rpc_common_service_proto_rawDesc = []byte{ 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x65, 0x6e, - 0x64, 0x4c, 0x69, 0x6e, 0x65, 0x22, 0xb6, 0x02, 0x0a, 0x10, 0x4d, 0x69, 0x73, 0x63, 0x6f, 0x6e, + 0x64, 0x4c, 0x69, 0x6e, 0x65, 0x22, 0xff, 0x01, 0x0a, 0x10, 0x4d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, @@ -2498,300 +2490,296 @@ var file_rpc_common_service_proto_rawDesc = []byte{ 0x75, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x08, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, - 0x73, 0x12, 0x3b, 0x0a, 0x0a, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x52, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x52, 0x0a, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xf3, - 0x01, 0x0a, 0x0d, 0x4d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x45, 0x0a, 0x0f, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, - 0x0e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x42, 0x0a, 0x0e, 0x63, 0x61, 0x75, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x61, 0x75, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x63, 0x61, 0x75, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x07, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x52, - 0x02, 0x69, 0x64, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, - 0x72, 0x69, 0x74, 0x79, 0x22, 0xf0, 0x01, 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x64, 0x76, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x64, 0x76, 0x49, 0x64, 0x12, 0x12, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, - 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, - 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2f, 0x0a, 0x13, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x12, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x65, 0x64, - 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x22, 0xf7, 0x03, 0x0a, 0x18, 0x44, 0x65, 0x74, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x4d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, - 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x73, 0x6f, - 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, - 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, - 0x72, 0x69, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x74, 0x72, 0x69, - 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, - 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1f, 0x0a, 0x0b, - 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x55, 0x72, 0x6c, 0x12, 0x1e, 0x0a, - 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x29, 0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x0c, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, - 0x12, 0x42, 0x0a, 0x0e, 0x63, 0x61, 0x75, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, - 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x61, 0x75, 0x73, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x63, 0x61, 0x75, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x76, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x0e, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x76, 0x64, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x22, 0xff, 0x09, 0x0a, 0x0d, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, - 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x64, 0x12, 0x19, - 0x0a, 0x08, 0x70, 0x6b, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x70, 0x6b, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, 0x73, - 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, - 0x69, 0x78, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, - 0x69, 0x74, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, + 0x73, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0xf3, 0x01, 0x0a, 0x0d, 0x4d, 0x69, 0x73, 0x63, + 0x6f, 0x6e, 0x66, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x45, 0x0a, 0x0f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x72, 0x69, + 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x42, 0x0a, 0x0e, 0x63, 0x61, 0x75, 0x73, + 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x43, 0x61, 0x75, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x63, + 0x61, 0x75, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4a, 0x04, 0x08, 0x03, + 0x10, 0x07, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x52, 0x02, 0x69, 0x64, 0x52, 0x05, 0x74, 0x69, + 0x74, 0x6c, 0x65, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x22, 0xf0, 0x01, + 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x15, 0x0a, 0x06, 0x61, 0x64, 0x76, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x61, 0x64, 0x76, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, + 0x69, 0x74, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, - 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x70, 0x6b, 0x67, 0x5f, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, - 0x6b, 0x67, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0d, 0x70, 0x6b, - 0x67, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x29, 0x0a, 0x05, 0x6c, - 0x61, 0x79, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x69, - 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, - 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, - 0x74, 0x79, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, - 0x39, 0x0a, 0x04, 0x63, 0x76, 0x73, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 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, 0x2e, 0x43, 0x76, 0x73, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x63, 0x76, 0x73, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x77, - 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x63, 0x77, 0x65, - 0x49, 0x64, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x75, - 0x72, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, - 0x79, 0x55, 0x72, 0x6c, 0x12, 0x41, 0x0a, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, - 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, + 0x2f, 0x0a, 0x13, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x72, 0x65, + 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x08, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, + 0x22, 0xf7, 0x03, 0x0a, 0x18, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x69, 0x73, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x32, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, + 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, + 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6d, + 0x61, 0x72, 0x79, 0x55, 0x72, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x29, + 0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, + 0x65, 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x0e, 0x63, 0x61, 0x75, + 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0d, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2e, 0x43, 0x61, 0x75, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, + 0x63, 0x61, 0x75, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x15, 0x0a, + 0x06, 0x61, 0x76, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, + 0x76, 0x64, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x0f, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x22, 0xff, 0x09, 0x0a, 0x0d, 0x56, + 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x29, 0x0a, 0x10, + 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6b, 0x67, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x6b, 0x67, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x5f, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x23, 0x0a, 0x0d, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x69, 0x78, 0x65, 0x64, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x08, + 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, + 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, + 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, + 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x08, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, + 0x12, 0x42, 0x0a, 0x0e, 0x70, 0x6b, 0x67, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, + 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x6b, 0x67, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0d, 0x70, 0x6b, 0x67, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x66, 0x69, 0x65, 0x72, 0x12, 0x29, 0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, + 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, + 0x74, 0x79, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x63, 0x76, 0x73, 0x73, + 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 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, 0x2e, 0x43, 0x76, 0x73, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x63, + 0x76, 0x73, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x77, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0d, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x63, 0x77, 0x65, 0x49, 0x64, 0x73, 0x12, 0x1f, 0x0a, 0x0b, + 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x55, 0x72, 0x6c, 0x12, 0x41, 0x0a, + 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, + 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, + 0x12, 0x48, 0x0a, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, + 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, - 0x68, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x12, 0x48, 0x0a, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x5f, - 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x10, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x10, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x44, 0x61, 0x74, - 0x65, 0x12, 0x48, 0x0a, 0x14, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x61, 0x64, 0x76, 0x69, - 0x73, 0x6f, 0x72, 0x79, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x41, - 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, 0x10, 0x63, - 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x76, 0x75, 0x6c, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x63, - 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x56, 0x75, 0x6c, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, - 0x0a, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x13, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x09, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x49, 0x64, 0x73, 0x12, 0x39, 0x0a, 0x0b, - 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0a, 0x64, 0x61, 0x74, - 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x76, 0x65, 0x6e, 0x64, 0x6f, - 0x72, 0x5f, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x15, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x2f, 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, 0x2e, 0x56, 0x65, - 0x6e, 0x64, 0x6f, 0x72, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x0e, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, - 0x79, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6b, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x16, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x6b, 0x67, 0x50, 0x61, 0x74, 0x68, 0x12, 0x15, 0x0a, 0x06, - 0x70, 0x6b, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x6b, - 0x67, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x18, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x4b, 0x0a, 0x09, 0x43, - 0x76, 0x73, 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, 0x28, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x72, 0x69, 0x76, - 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x56, 0x53, 0x53, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x59, 0x0a, 0x13, 0x56, 0x65, 0x6e, 0x64, - 0x6f, 0x72, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x16, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, - 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0x42, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x57, 0x0a, 0x05, 0x4c, 0x61, 0x79, 0x65, 0x72, - 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x69, 0x66, 0x66, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x66, 0x66, 0x49, - 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, - 0x22, 0xc3, 0x01, 0x0a, 0x0d, 0x43, 0x61, 0x75, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1a, - 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6c, 0x69, - 0x6e, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4c, - 0x69, 0x6e, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x26, - 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, - 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x64, 0x65, - 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x76, 0x0a, 0x04, 0x43, 0x56, 0x53, 0x53, 0x12, 0x1b, - 0x0a, 0x09, 0x76, 0x32, 0x5f, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x76, 0x32, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x76, - 0x33, 0x5f, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x76, 0x33, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x32, 0x5f, 0x73, - 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x76, 0x32, 0x53, 0x63, - 0x6f, 0x72, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x33, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x76, 0x33, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x98, - 0x01, 0x0a, 0x0e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, - 0x74, 0x68, 0x12, 0x29, 0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x2a, 0x0a, - 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xf3, 0x01, 0x0a, 0x04, 0x4c, 0x69, - 0x6e, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, - 0x1e, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x1c, 0x0a, 0x09, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x09, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x20, 0x0a, - 0x0b, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x12, - 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x22, - 0x30, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x6e, 0x65, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, - 0x73, 0x22, 0x9f, 0x02, 0x0a, 0x0d, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, - 0x69, 0x6e, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, - 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, - 0x72, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, - 0x72, 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, - 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x65, 0x6e, 0x64, - 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, + 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x12, 0x48, 0x0a, 0x14, 0x63, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x79, 0x5f, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x52, 0x12, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x79, + 0x44, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, 0x10, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x76, + 0x75, 0x6c, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x56, 0x75, + 0x6c, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, + 0x5f, 0x69, 0x64, 0x73, 0x18, 0x13, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x76, 0x65, 0x6e, 0x64, + 0x6f, 0x72, 0x49, 0x64, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x69, + 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x12, 0x58, 0x0a, 0x0f, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x73, 0x65, 0x76, 0x65, 0x72, + 0x69, 0x74, 0x79, 0x18, 0x15, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 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, 0x2e, 0x56, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x53, 0x65, 0x76, + 0x65, 0x72, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x76, 0x65, 0x6e, 0x64, + 0x6f, 0x72, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6b, + 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x6b, + 0x67, 0x50, 0x61, 0x74, 0x68, 0x12, 0x15, 0x0a, 0x06, 0x70, 0x6b, 0x67, 0x5f, 0x69, 0x64, 0x18, + 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x6b, 0x67, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x18, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x1a, 0x4b, 0x0a, 0x09, 0x43, 0x76, 0x73, 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, 0x28, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, - 0x6e, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, - 0x63, 0x68, 0x12, 0x29, 0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4a, 0x04, 0x08, - 0x09, 0x10, 0x0a, 0x22, 0x5d, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x69, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 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, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x73, 0x22, 0x99, 0x02, 0x0a, 0x0f, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4c, - 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, - 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, - 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, - 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x08, 0x63, 0x61, - 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x74, + 0x6e, 0x2e, 0x43, 0x56, 0x53, 0x53, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x1a, 0x59, 0x0a, 0x13, 0x56, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x53, 0x65, 0x76, 0x65, 0x72, + 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x74, 0x72, 0x69, 0x76, + 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, + 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x42, 0x0a, 0x0a, + 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, + 0x22, 0x57, 0x0a, 0x05, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, + 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, + 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x66, 0x66, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x22, 0xc3, 0x01, 0x0a, 0x0d, 0x43, 0x61, + 0x75, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x19, 0x0a, 0x08, + 0x65, 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, + 0x65, 0x6e, 0x64, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, + 0x76, 0x0a, 0x04, 0x43, 0x56, 0x53, 0x53, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x32, 0x5f, 0x76, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x32, 0x56, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x33, 0x5f, 0x76, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x33, 0x56, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x32, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x07, 0x76, 0x32, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x19, 0x0a, 0x08, + 0x76, 0x33, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, + 0x76, 0x33, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x98, 0x01, 0x0a, 0x0e, 0x43, 0x75, 0x73, 0x74, + 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, + 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x29, 0x0a, 0x05, 0x6c, + 0x61, 0x79, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x69, + 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, + 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x22, 0xf3, 0x01, 0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, + 0x08, 0x69, 0x73, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x69, 0x73, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72, 0x75, 0x6e, + 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x74, 0x72, 0x75, + 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, + 0x67, 0x68, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x68, 0x69, 0x67, + 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x72, 0x73, + 0x74, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x66, + 0x69, 0x72, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x61, 0x73, + 0x74, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6c, + 0x61, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x22, 0x30, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, + 0x69, 0x6e, 0x65, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x9f, 0x02, 0x0a, 0x0d, 0x53, + 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x17, 0x0a, 0x07, + 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, + 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, + 0x74, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x6e, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4c, 0x69, + 0x6e, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x26, 0x0a, + 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x72, + 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x52, + 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x29, 0x0a, 0x05, 0x6c, + 0x61, 0x79, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x69, + 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, + 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x22, 0x5d, 0x0a, 0x06, + 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, + 0x74, 0x68, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, + 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, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x99, 0x02, 0x0a, 0x0f, + 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, + 0x32, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x16, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, + 0x69, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, + 0x67, 0x6f, 0x72, 0x79, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, + 0x6f, 0x72, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6b, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x6b, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, + 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x02, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, + 0x69, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x22, 0xed, 0x01, 0x0a, 0x0b, 0x4c, 0x69, 0x63, 0x65, + 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e, + 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, + 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x63, + 0x65, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0b, 0x6c, + 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, + 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, + 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6b, 0x67, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x6b, 0x67, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x69, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x52, 0x08, 0x66, 0x69, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x29, 0x0a, 0x05, + 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, + 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, + 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x22, 0x98, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x63, 0x65, + 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x3e, 0x0a, 0x08, 0x63, 0x61, + 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x2e, 0x45, 0x6e, 0x75, 0x6d, - 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6b, - 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x6b, - 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, - 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, - 0x65, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, - 0x78, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x22, 0xed, - 0x01, 0x0a, 0x0b, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x41, - 0x0a, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x2e, - 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0b, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, - 0x0a, 0x08, 0x70, 0x6b, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x70, 0x6b, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x69, 0x6e, - 0x67, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x72, - 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, - 0x73, 0x65, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x66, 0x69, 0x6e, 0x67, 0x69, - 0x6e, 0x67, 0x73, 0x12, 0x29, 0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, - 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x22, 0x98, - 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x12, 0x3e, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, - 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, - 0x72, 0x79, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, - 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, - 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x22, 0x95, 0x01, 0x0a, 0x0f, 0x4c, 0x69, - 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x22, 0x81, 0x01, - 0x0a, 0x04, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x42, 0x49, - 0x44, 0x44, 0x45, 0x4e, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x53, 0x54, 0x52, 0x49, - 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x43, 0x49, 0x50, 0x52, - 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x54, 0x49, 0x43, 0x45, - 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x56, 0x45, - 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x4e, 0x45, 0x4e, 0x43, 0x55, 0x4d, 0x42, 0x45, 0x52, - 0x45, 0x44, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, - 0x07, 0x22, 0x4e, 0x0a, 0x0b, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x22, 0x3f, 0x0a, 0x04, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x50, 0x4b, - 0x47, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x10, 0x02, 0x12, - 0x10, 0x0a, 0x0c, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, - 0x03, 0x2a, 0x44, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x0b, 0x0a, - 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4c, 0x4f, - 0x57, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x45, 0x44, 0x49, 0x55, 0x4d, 0x10, 0x02, 0x12, - 0x08, 0x0a, 0x04, 0x48, 0x49, 0x47, 0x48, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x52, 0x49, - 0x54, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x04, 0x42, 0x31, 0x5a, 0x2f, 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, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, + 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x02, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, + 0x6e, 0x6b, 0x22, 0x95, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, + 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x22, 0x81, 0x01, 0x0a, 0x04, 0x45, 0x6e, 0x75, 0x6d, 0x12, + 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x42, 0x49, 0x44, 0x44, 0x45, 0x4e, 0x10, 0x01, 0x12, + 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x53, 0x54, 0x52, 0x49, 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, + 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x43, 0x49, 0x50, 0x52, 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x03, 0x12, + 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x54, 0x49, 0x43, 0x45, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x50, + 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x56, 0x45, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x55, + 0x4e, 0x45, 0x4e, 0x43, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x45, 0x44, 0x10, 0x06, 0x12, 0x0b, 0x0a, + 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x07, 0x22, 0x4e, 0x0a, 0x0b, 0x4c, 0x69, + 0x63, 0x65, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3f, 0x0a, 0x04, 0x45, 0x6e, 0x75, + 0x6d, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x50, 0x4b, 0x47, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, + 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x49, 0x43, 0x45, + 0x4e, 0x53, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x03, 0x2a, 0x44, 0x0a, 0x08, 0x53, 0x65, + 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4c, 0x4f, 0x57, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, + 0x4d, 0x45, 0x44, 0x49, 0x55, 0x4d, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x49, 0x47, 0x48, + 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x52, 0x49, 0x54, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x04, + 0x42, 0x31, 0x5a, 0x2f, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x3b, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2852,42 +2840,41 @@ var file_rpc_common_service_proto_depIdxs = []int32{ 11, // 5: trivy.common.Misconfiguration.successes:type_name -> trivy.common.MisconfResult 11, // 6: trivy.common.Misconfiguration.warnings:type_name -> trivy.common.MisconfResult 11, // 7: trivy.common.Misconfiguration.failures:type_name -> trivy.common.MisconfResult - 11, // 8: trivy.common.Misconfiguration.exceptions:type_name -> trivy.common.MisconfResult - 12, // 9: trivy.common.MisconfResult.policy_metadata:type_name -> trivy.common.PolicyMetadata - 17, // 10: trivy.common.MisconfResult.cause_metadata:type_name -> trivy.common.CauseMetadata - 0, // 11: trivy.common.DetectedMisconfiguration.severity:type_name -> trivy.common.Severity - 16, // 12: trivy.common.DetectedMisconfiguration.layer:type_name -> trivy.common.Layer - 17, // 13: trivy.common.DetectedMisconfiguration.cause_metadata:type_name -> trivy.common.CauseMetadata - 0, // 14: trivy.common.Vulnerability.severity:type_name -> trivy.common.Severity - 8, // 15: trivy.common.Vulnerability.pkg_identifier:type_name -> trivy.common.PkgIdentifier - 16, // 16: trivy.common.Vulnerability.layer:type_name -> trivy.common.Layer - 29, // 17: trivy.common.Vulnerability.cvss:type_name -> trivy.common.Vulnerability.CvssEntry - 31, // 18: trivy.common.Vulnerability.published_date:type_name -> google.protobuf.Timestamp - 31, // 19: trivy.common.Vulnerability.last_modified_date:type_name -> google.protobuf.Timestamp - 32, // 20: trivy.common.Vulnerability.custom_advisory_data:type_name -> google.protobuf.Value - 32, // 21: trivy.common.Vulnerability.custom_vuln_data:type_name -> google.protobuf.Value - 15, // 22: trivy.common.Vulnerability.data_source:type_name -> trivy.common.DataSource - 30, // 23: trivy.common.Vulnerability.vendor_severity:type_name -> trivy.common.Vulnerability.VendorSeverityEntry - 21, // 24: trivy.common.CauseMetadata.code:type_name -> trivy.common.Code - 16, // 25: trivy.common.CustomResource.layer:type_name -> trivy.common.Layer - 32, // 26: trivy.common.CustomResource.data:type_name -> google.protobuf.Value - 20, // 27: trivy.common.Code.lines:type_name -> trivy.common.Line - 21, // 28: trivy.common.SecretFinding.code:type_name -> trivy.common.Code - 16, // 29: trivy.common.SecretFinding.layer:type_name -> trivy.common.Layer - 22, // 30: trivy.common.Secret.findings:type_name -> trivy.common.SecretFinding - 0, // 31: trivy.common.DetectedLicense.severity:type_name -> trivy.common.Severity - 1, // 32: trivy.common.DetectedLicense.category:type_name -> trivy.common.LicenseCategory.Enum - 2, // 33: trivy.common.LicenseFile.license_type:type_name -> trivy.common.LicenseType.Enum - 26, // 34: trivy.common.LicenseFile.fingings:type_name -> trivy.common.LicenseFinding - 16, // 35: trivy.common.LicenseFile.layer:type_name -> trivy.common.Layer - 1, // 36: trivy.common.LicenseFinding.category:type_name -> trivy.common.LicenseCategory.Enum - 18, // 37: trivy.common.Vulnerability.CvssEntry.value:type_name -> trivy.common.CVSS - 0, // 38: trivy.common.Vulnerability.VendorSeverityEntry.value:type_name -> trivy.common.Severity - 39, // [39:39] is the sub-list for method output_type - 39, // [39:39] is the sub-list for method input_type - 39, // [39:39] is the sub-list for extension type_name - 39, // [39:39] is the sub-list for extension extendee - 0, // [0:39] is the sub-list for field type_name + 12, // 8: trivy.common.MisconfResult.policy_metadata:type_name -> trivy.common.PolicyMetadata + 17, // 9: trivy.common.MisconfResult.cause_metadata:type_name -> trivy.common.CauseMetadata + 0, // 10: trivy.common.DetectedMisconfiguration.severity:type_name -> trivy.common.Severity + 16, // 11: trivy.common.DetectedMisconfiguration.layer:type_name -> trivy.common.Layer + 17, // 12: trivy.common.DetectedMisconfiguration.cause_metadata:type_name -> trivy.common.CauseMetadata + 0, // 13: trivy.common.Vulnerability.severity:type_name -> trivy.common.Severity + 8, // 14: trivy.common.Vulnerability.pkg_identifier:type_name -> trivy.common.PkgIdentifier + 16, // 15: trivy.common.Vulnerability.layer:type_name -> trivy.common.Layer + 29, // 16: trivy.common.Vulnerability.cvss:type_name -> trivy.common.Vulnerability.CvssEntry + 31, // 17: trivy.common.Vulnerability.published_date:type_name -> google.protobuf.Timestamp + 31, // 18: trivy.common.Vulnerability.last_modified_date:type_name -> google.protobuf.Timestamp + 32, // 19: trivy.common.Vulnerability.custom_advisory_data:type_name -> google.protobuf.Value + 32, // 20: trivy.common.Vulnerability.custom_vuln_data:type_name -> google.protobuf.Value + 15, // 21: trivy.common.Vulnerability.data_source:type_name -> trivy.common.DataSource + 30, // 22: trivy.common.Vulnerability.vendor_severity:type_name -> trivy.common.Vulnerability.VendorSeverityEntry + 21, // 23: trivy.common.CauseMetadata.code:type_name -> trivy.common.Code + 16, // 24: trivy.common.CustomResource.layer:type_name -> trivy.common.Layer + 32, // 25: trivy.common.CustomResource.data:type_name -> google.protobuf.Value + 20, // 26: trivy.common.Code.lines:type_name -> trivy.common.Line + 21, // 27: trivy.common.SecretFinding.code:type_name -> trivy.common.Code + 16, // 28: trivy.common.SecretFinding.layer:type_name -> trivy.common.Layer + 22, // 29: trivy.common.Secret.findings:type_name -> trivy.common.SecretFinding + 0, // 30: trivy.common.DetectedLicense.severity:type_name -> trivy.common.Severity + 1, // 31: trivy.common.DetectedLicense.category:type_name -> trivy.common.LicenseCategory.Enum + 2, // 32: trivy.common.LicenseFile.license_type:type_name -> trivy.common.LicenseType.Enum + 26, // 33: trivy.common.LicenseFile.fingings:type_name -> trivy.common.LicenseFinding + 16, // 34: trivy.common.LicenseFile.layer:type_name -> trivy.common.Layer + 1, // 35: trivy.common.LicenseFinding.category:type_name -> trivy.common.LicenseCategory.Enum + 18, // 36: trivy.common.Vulnerability.CvssEntry.value:type_name -> trivy.common.CVSS + 0, // 37: trivy.common.Vulnerability.VendorSeverityEntry.value:type_name -> trivy.common.Severity + 38, // [38:38] is the sub-list for method output_type + 38, // [38:38] is the sub-list for method input_type + 38, // [38:38] is the sub-list for extension type_name + 38, // [38:38] is the sub-list for extension extendee + 0, // [0:38] is the sub-list for field type_name } func init() { file_rpc_common_service_proto_init() } diff --git a/rpc/common/service.proto b/rpc/common/service.proto index d80bf57e3b86..e989738c285b 100644 --- a/rpc/common/service.proto +++ b/rpc/common/service.proto @@ -73,7 +73,8 @@ message Misconfiguration { repeated MisconfResult successes = 3; repeated MisconfResult warnings = 4; repeated MisconfResult failures = 5; - repeated MisconfResult exceptions = 6; + + reserved 6; // deprecated 'exceptions' } message MisconfResult { From 6fab88dd56c257ef2cc63b617c2a5decb1c4cf98 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Wed, 30 Oct 2024 04:47:26 +0600 Subject: [PATCH 72/94] fix(helm): properly handle multiple archived dependencies (#7782) Signed-off-by: nikpivkin --- pkg/iac/scanners/helm/parser/parser.go | 47 ++++++++++++------ pkg/iac/scanners/helm/parser/parser_test.go | 30 +++++++++++ .../multiple-archived-deps/Chart.yaml | 14 ++++++ .../charts/common-2.26.0.tgz | Bin 0 -> 15573 bytes .../opentelemetry-collector-0.108.0.tgz | Bin 0 -> 34993 bytes .../testdata/non-deps-archives/Chart.yaml | 14 ++++++ .../backup_charts/mysql-operator-2.2.2.tgz | Bin 0 -> 11892 bytes .../wordpress-operator-0.12.4.tgz | Bin 0 -> 38731 bytes 8 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 pkg/iac/scanners/helm/parser/testdata/multiple-archived-deps/Chart.yaml create mode 100644 pkg/iac/scanners/helm/parser/testdata/multiple-archived-deps/charts/common-2.26.0.tgz create mode 100644 pkg/iac/scanners/helm/parser/testdata/multiple-archived-deps/charts/opentelemetry-collector-0.108.0.tgz create mode 100644 pkg/iac/scanners/helm/parser/testdata/non-deps-archives/Chart.yaml create mode 100644 pkg/iac/scanners/helm/parser/testdata/non-deps-archives/backup_charts/mysql-operator-2.2.2.tgz create mode 100644 pkg/iac/scanners/helm/parser/testdata/non-deps-archives/backup_charts/wordpress-operator-0.12.4.tgz diff --git a/pkg/iac/scanners/helm/parser/parser.go b/pkg/iac/scanners/helm/parser/parser.go index e38f032b6221..1a132fdc2f76 100644 --- a/pkg/iac/scanners/helm/parser/parser.go +++ b/pkg/iac/scanners/helm/parser/parser.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io/fs" + "path" "path/filepath" "regexp" "sort" @@ -46,7 +47,7 @@ type ChartFile struct { ManifestContent string } -func New(path string, opts ...Option) (*Parser, error) { +func New(src string, opts ...Option) (*Parser, error) { client := action.NewInstall(&action.Configuration{}) client.DryRun = true // don't do anything @@ -55,7 +56,7 @@ func New(path string, opts ...Option) (*Parser, error) { p := &Parser{ helmClient: client, - ChartSource: path, + ChartSource: src, logger: log.WithPrefix("helm parser"), } @@ -79,10 +80,10 @@ func New(path string, opts ...Option) (*Parser, error) { return p, nil } -func (p *Parser) ParseFS(ctx context.Context, target fs.FS, path string) error { - p.workingFS = target +func (p *Parser) ParseFS(ctx context.Context, fsys fs.FS, target string) error { + p.workingFS = fsys - if err := fs.WalkDir(p.workingFS, filepath.ToSlash(path), func(path string, entry fs.DirEntry, err error) error { + if err := fs.WalkDir(p.workingFS, filepath.ToSlash(target), func(filePath string, entry fs.DirEntry, err error) error { select { case <-ctx.Done(): return ctx.Err() @@ -95,16 +96,20 @@ func (p *Parser) ParseFS(ctx context.Context, target fs.FS, path string) error { return nil } - if detection.IsArchive(path) { - tarFS, err := p.addTarToFS(path) + if _, err := fs.Stat(p.workingFS, filePath); err != nil { + return nil + } + + if detection.IsArchive(filePath) && !isDependencyChartArchive(p.workingFS, filePath) { + tarFS, err := p.addTarToFS(filePath) if errors.Is(err, errSkipFS) { // an unpacked Chart already exists return nil } else if err != nil { - return fmt.Errorf("failed to add tar %q to FS: %w", path, err) + return fmt.Errorf("failed to add tar %q to FS: %w", filePath, err) } - targetPath := filepath.Dir(path) + targetPath := filepath.Dir(filePath) if targetPath == "" { targetPath = "." } @@ -114,7 +119,7 @@ func (p *Parser) ParseFS(ctx context.Context, target fs.FS, path string) error { } return nil } else { - return p.addPaths(path) + return p.addPaths(filePath) } }); err != nil { return fmt.Errorf("walk dir error: %w", err) @@ -123,19 +128,29 @@ func (p *Parser) ParseFS(ctx context.Context, target fs.FS, path string) error { return nil } +func isDependencyChartArchive(fsys fs.FS, archivePath string) bool { + parent := path.Dir(archivePath) + if path.Base(parent) != "charts" { + return false + } + + _, err := fs.Stat(fsys, path.Join(parent, "..", "Chart.yaml")) + return err == nil +} + func (p *Parser) addPaths(paths ...string) error { - for _, path := range paths { - if _, err := fs.Stat(p.workingFS, path); err != nil { + for _, filePath := range paths { + if _, err := fs.Stat(p.workingFS, filePath); err != nil { return err } - if strings.HasSuffix(path, "Chart.yaml") && p.rootPath == "" { - if err := p.extractChartName(path); err != nil { + if strings.HasSuffix(filePath, "Chart.yaml") && p.rootPath == "" { + if err := p.extractChartName(filePath); err != nil { return err } - p.rootPath = filepath.Dir(path) + p.rootPath = filepath.Dir(filePath) } - p.filepaths = append(p.filepaths, path) + p.filepaths = append(p.filepaths, filePath) } return nil } diff --git a/pkg/iac/scanners/helm/parser/parser_test.go b/pkg/iac/scanners/helm/parser/parser_test.go index 9c8b05ce7696..01aa697d559c 100644 --- a/pkg/iac/scanners/helm/parser/parser_test.go +++ b/pkg/iac/scanners/helm/parser/parser_test.go @@ -48,4 +48,34 @@ func TestParseFS(t *testing.T) { } assert.Equal(t, expectedFiles, p.filepaths) }) + + t.Run("chart with multiple archived deps", func(t *testing.T) { + p, err := New(".") + require.NoError(t, err) + + fsys := os.DirFS(filepath.Join("testdata", "multiple-archived-deps")) + require.NoError(t, p.ParseFS(context.TODO(), fsys, ".")) + + expectedFiles := []string{ + "Chart.yaml", + "charts/common-2.26.0.tgz", + "charts/opentelemetry-collector-0.108.0.tgz", + } + assert.Equal(t, expectedFiles, p.filepaths) + }) + + t.Run("archives are not dependencies", func(t *testing.T) { + p, err := New(".") + require.NoError(t, err) + + fsys := os.DirFS(filepath.Join("testdata", "non-deps-archives")) + require.NoError(t, p.ParseFS(context.TODO(), fsys, ".")) + + expectedFiles := []string{ + "Chart.yaml", + "backup_charts/wordpress-operator/Chart.yaml", + "backup_charts/mysql-operator/Chart.yaml", + } + assert.Subset(t, p.filepaths, expectedFiles) + }) } diff --git a/pkg/iac/scanners/helm/parser/testdata/multiple-archived-deps/Chart.yaml b/pkg/iac/scanners/helm/parser/testdata/multiple-archived-deps/Chart.yaml new file mode 100644 index 000000000000..82d6c918088f --- /dev/null +++ b/pkg/iac/scanners/helm/parser/testdata/multiple-archived-deps/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +appVersion: "1.1" +description: Test Chart +name: y-chart +version: 1.0.0 +kubeVersion: ">=1.21" + +dependencies: + - name: common + repository: https://charts.bitnami.com/bitnami + version: 2.26.0 + - name: opentelemetry-collector + version: 0.108.0 + repository: https://open-telemetry.github.io/opentelemetry-helm-charts \ No newline at end of file diff --git a/pkg/iac/scanners/helm/parser/testdata/multiple-archived-deps/charts/common-2.26.0.tgz b/pkg/iac/scanners/helm/parser/testdata/multiple-archived-deps/charts/common-2.26.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..43f85ba36a9160d8ee712e11c22de7732a8f53db GIT binary patch literal 15573 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 X(}Twu8&x6#fdIf*neT%*tcmy!-ZISW literal 0 HcmV?d00001 diff --git a/pkg/iac/scanners/helm/parser/testdata/non-deps-archives/Chart.yaml b/pkg/iac/scanners/helm/parser/testdata/non-deps-archives/Chart.yaml new file mode 100644 index 000000000000..65225b732935 --- /dev/null +++ b/pkg/iac/scanners/helm/parser/testdata/non-deps-archives/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +appVersion: "1.1" +description: Test Chart +name: y-chart +version: 1.0.0 +kubeVersion: ">=1.21" + +dependencies: + - name: mysql-operator + repository: https://mysql.github.io/mysql-operator/ + version: 2.2.2 + - name: wordpress-operator + version: 0.12.4 + repository: https://helm-charts.bitpoke.io \ No newline at end of file diff --git a/pkg/iac/scanners/helm/parser/testdata/non-deps-archives/backup_charts/mysql-operator-2.2.2.tgz b/pkg/iac/scanners/helm/parser/testdata/non-deps-archives/backup_charts/mysql-operator-2.2.2.tgz new file mode 100644 index 0000000000000000000000000000000000000000..b80fc3c0425e174020f5829338d436dceda8b322 GIT binary patch literal 11892 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 literal 0 HcmV?d00001 diff --git a/pkg/iac/scanners/helm/parser/testdata/non-deps-archives/backup_charts/wordpress-operator-0.12.4.tgz b/pkg/iac/scanners/helm/parser/testdata/non-deps-archives/backup_charts/wordpress-operator-0.12.4.tgz new file mode 100644 index 0000000000000000000000000000000000000000..4086e9f1a6bab460c3517d28d39566d0226371d2 GIT binary patch literal 38731 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 literal 0 HcmV?d00001 From b661d680ff0372c8e4beea0db13bf69d6a2203a8 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Wed, 30 Oct 2024 16:16:02 +0600 Subject: [PATCH 73/94] fix(cli): add config name to skip-policy-update alias (#7820) Signed-off-by: nikpivkin --- pkg/flag/rego_flags.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/flag/rego_flags.go b/pkg/flag/rego_flags.go index 4b291f0a5eb3..84e0aed910f4 100644 --- a/pkg/flag/rego_flags.go +++ b/pkg/flag/rego_flags.go @@ -19,6 +19,7 @@ var ( Aliases: []Alias{ { Name: "skip-policy-update", + ConfigName: "rego.skip-policy-update", Deprecated: true, }, }, From f2bb9c6227743dd61f44eb591d4b15192fe110c6 Mon Sep 17 00:00:00 2001 From: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:32:40 +0600 Subject: [PATCH 74/94] fix(sbom): use `Annotation` instead of `AttributionTexts` for `SPDX` formats (#7811) --- integration/testdata/conda-spdx.json.golden | 39 +++-- integration/testdata/julia-spdx.json.golden | 93 +++++++--- pkg/sbom/spdx/marshal.go | 42 +++-- pkg/sbom/spdx/marshal_test.go | 184 +++++++++++--------- pkg/sbom/spdx/testdata/happy/bom.json | 98 +++++++++-- pkg/sbom/spdx/unmarshal.go | 18 +- 6 files changed, 316 insertions(+), 158 deletions(-) diff --git a/integration/testdata/conda-spdx.json.golden b/integration/testdata/conda-spdx.json.golden index c14d1bf4e018..c11f52eeca1b 100644 --- a/integration/testdata/conda-spdx.json.golden +++ b/integration/testdata/conda-spdx.json.golden @@ -31,10 +31,15 @@ "referenceLocator": "pkg:conda/openssl@1.1.1q" } ], - "attributionTexts": [ - "PkgType: conda-pkg" - ], - "primaryPackagePurpose": "LIBRARY" + "primaryPackagePurpose": "LIBRARY", + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2021-08-25T12:20:30Z", + "annotationType": "OTHER", + "comment": "PkgType: conda-pkg" + } + ] }, { "name": "pip", @@ -55,20 +60,30 @@ "referenceLocator": "pkg:conda/pip@22.2.2" } ], - "attributionTexts": [ - "PkgType: conda-pkg" - ], - "primaryPackagePurpose": "LIBRARY" + "primaryPackagePurpose": "LIBRARY", + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2021-08-25T12:20:30Z", + "annotationType": "OTHER", + "comment": "PkgType: conda-pkg" + } + ] }, { "name": "testdata/fixtures/repo/conda", "SPDXID": "SPDXRef-Filesystem-2e2426fd0f2580ef", "downloadLocation": "NONE", "filesAnalyzed": false, - "attributionTexts": [ - "SchemaVersion: 2" - ], - "primaryPackagePurpose": "SOURCE" + "primaryPackagePurpose": "SOURCE", + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2021-08-25T12:20:30Z", + "annotationType": "OTHER", + "comment": "SchemaVersion: 2" + } + ] } ], "files": [ diff --git a/integration/testdata/julia-spdx.json.golden b/integration/testdata/julia-spdx.json.golden index 89a4edb3f287..a770765dd849 100644 --- a/integration/testdata/julia-spdx.json.golden +++ b/integration/testdata/julia-spdx.json.golden @@ -17,11 +17,21 @@ "SPDXID": "SPDXRef-Application-18fc3597717a3e56", "downloadLocation": "NONE", "filesAnalyzed": false, - "attributionTexts": [ - "Class: lang-pkgs", - "Type: julia" - ], - "primaryPackagePurpose": "APPLICATION" + "primaryPackagePurpose": "APPLICATION", + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2021-08-25T12:20:30Z", + "annotationType": "OTHER", + "comment": "Class: lang-pkgs" + }, + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2021-08-25T12:20:30Z", + "annotationType": "OTHER", + "comment": "Type: julia" + } + ] }, { "name": "A", @@ -40,11 +50,21 @@ "referenceLocator": "pkg:julia/A@1.9.0?uuid=ead4f63c-334e-11e9-00e6-e7f0a5f21b60" } ], - "attributionTexts": [ - "PkgID: ead4f63c-334e-11e9-00e6-e7f0a5f21b60", - "PkgType: julia" - ], - "primaryPackagePurpose": "LIBRARY" + "primaryPackagePurpose": "LIBRARY", + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2021-08-25T12:20:30Z", + "annotationType": "OTHER", + "comment": "PkgID: ead4f63c-334e-11e9-00e6-e7f0a5f21b60" + }, + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2021-08-25T12:20:30Z", + "annotationType": "OTHER", + "comment": "PkgType: julia" + } + ] }, { "name": "B", @@ -63,11 +83,21 @@ "referenceLocator": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24" } ], - "attributionTexts": [ - "PkgID: f41f7b98-334e-11e9-1257-49272045fb24", - "PkgType: julia" - ], - "primaryPackagePurpose": "LIBRARY" + "primaryPackagePurpose": "LIBRARY", + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2021-08-25T12:20:30Z", + "annotationType": "OTHER", + "comment": "PkgID: f41f7b98-334e-11e9-1257-49272045fb24" + }, + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2021-08-25T12:20:30Z", + "annotationType": "OTHER", + "comment": "PkgType: julia" + } + ] }, { "name": "B", @@ -86,21 +116,36 @@ "referenceLocator": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c" } ], - "attributionTexts": [ - "PkgID: edca9bc6-334e-11e9-3554-9595dbb4349c", - "PkgType: julia" - ], - "primaryPackagePurpose": "LIBRARY" + "primaryPackagePurpose": "LIBRARY", + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2021-08-25T12:20:30Z", + "annotationType": "OTHER", + "comment": "PkgID: edca9bc6-334e-11e9-3554-9595dbb4349c" + }, + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2021-08-25T12:20:30Z", + "annotationType": "OTHER", + "comment": "PkgType: julia" + } + ] }, { "name": "testdata/fixtures/repo/julia", "SPDXID": "SPDXRef-Filesystem-1be792dd0077c431", "downloadLocation": "NONE", "filesAnalyzed": false, - "attributionTexts": [ - "SchemaVersion: 2" - ], - "primaryPackagePurpose": "SOURCE" + "primaryPackagePurpose": "SOURCE", + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2021-08-25T12:20:30Z", + "annotationType": "OTHER", + "comment": "SchemaVersion: 2" + } + ] } ], "relationships": [ diff --git a/pkg/sbom/spdx/marshal.go b/pkg/sbom/spdx/marshal.go index 809ce95d7e4c..51f9144f682d 100644 --- a/pkg/sbom/spdx/marshal.go +++ b/pkg/sbom/spdx/marshal.go @@ -50,6 +50,8 @@ const ( PackageSupplierNoAssertion = "NOASSERTION" PackageSupplierOrganization = "Organization" + PackageAnnotatorToolField = "Tool" + RelationShipContains = common.TypeRelationshipContains RelationShipDescribe = common.TypeRelationshipDescribe RelationShipDependsOn = common.TypeRelationshipDependsOn @@ -122,6 +124,9 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document, packages []*spdx.Package ) + // Lock time to use same time for all spdx fields + timeNow := clock.Now(ctx).UTC().Format(time.RFC3339) + root := bom.Root() pkgDownloadLocation := m.packageDownloadLocation(root) @@ -129,7 +134,7 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document, packageIDs := make(map[uuid.UUID]spdx.ElementID) // Root package contains OS, OS packages, language-specific packages and so on. - rootPkg, err := m.rootSPDXPackage(root, pkgDownloadLocation) + rootPkg, err := m.rootSPDXPackage(root, timeNow, pkgDownloadLocation) if err != nil { return nil, xerrors.Errorf("failed to generate a root package: %w", err) } @@ -144,7 +149,7 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document, if c.Root { continue } - spdxPackage, err := m.spdxPackage(c, pkgDownloadLocation) + spdxPackage, err := m.spdxPackage(c, timeNow, pkgDownloadLocation) if err != nil { return nil, xerrors.Errorf("spdx package error: %w", err) } @@ -216,7 +221,7 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document, CreatorType: "Tool", }, }, - Created: clock.Now(ctx).UTC().Format(time.RFC3339), + Created: timeNow, }, Packages: packages, Relationships: relationShips, @@ -237,7 +242,7 @@ func (m *Marshaler) packageDownloadLocation(root *core.Component) string { return location } -func (m *Marshaler) rootSPDXPackage(root *core.Component, pkgDownloadLocation string) (*spdx.Package, error) { +func (m *Marshaler) rootSPDXPackage(root *core.Component, timeNow, pkgDownloadLocation string) (*spdx.Package, error) { var externalReferences []*spdx.PackageExternalReference // When the target is a container image, add PURL to the external references of the root package. if root.PkgIdentifier.PURL != nil { @@ -258,17 +263,25 @@ func (m *Marshaler) rootSPDXPackage(root *core.Component, pkgDownloadLocation st PackageName: root.Name, PackageSPDXIdentifier: elementID(camelCase(string(root.Type)), pkgID), PackageDownloadLocation: pkgDownloadLocation, - PackageAttributionTexts: m.spdxAttributionTexts(root), + Annotations: m.spdxAnnotations(root, timeNow), PackageExternalReferences: externalReferences, PrimaryPackagePurpose: pkgPurpose, }, nil } -func (m *Marshaler) appendAttributionText(attributionTexts []string, key, value string) []string { +func (m *Marshaler) appendAnnotation(annotations []spdx.Annotation, timeNow, key, value string) []spdx.Annotation { if value == "" { - return attributionTexts + return annotations } - return append(attributionTexts, fmt.Sprintf("%s: %s", key, value)) + return append(annotations, spdx.Annotation{ + AnnotationDate: timeNow, + AnnotationType: spdx.CategoryOther, + Annotator: spdx.Annotator{ + Annotator: fmt.Sprintf("%s-%s", CreatorTool, m.appVersion), + AnnotatorType: PackageAnnotatorToolField, + }, + AnnotationComment: fmt.Sprintf("%s: %s", key, value), + }) } func (m *Marshaler) purlExternalReference(packageURL string) *spdx.PackageExternalReference { @@ -287,7 +300,7 @@ func (m *Marshaler) advisoryExternalReference(primaryURL string) *spdx.PackageEx } } -func (m *Marshaler) spdxPackage(c *core.Component, pkgDownloadLocation string) (spdx.Package, error) { +func (m *Marshaler) spdxPackage(c *core.Component, timeNow, pkgDownloadLocation string) (spdx.Package, error) { pkgID, err := calcPkgID(m.hasher, c) if err != nil { return spdx.Package{}, xerrors.Errorf("failed to get os metadata package ID: %w", err) @@ -343,7 +356,7 @@ func (m *Marshaler) spdxPackage(c *core.Component, pkgDownloadLocation string) ( PrimaryPackagePurpose: purpose, PackageDownloadLocation: pkgDownloadLocation, PackageExternalReferences: pkgExtRefs, - PackageAttributionTexts: m.spdxAttributionTexts(c), + Annotations: m.spdxAnnotations(c, timeNow), PackageSourceInfo: sourceInfo, PackageSupplier: supplier, PackageChecksums: m.spdxChecksums(digests), @@ -365,16 +378,15 @@ func spdxPkgName(component *core.Component) string { } return component.Name } - -func (m *Marshaler) spdxAttributionTexts(c *core.Component) []string { - var texts []string +func (m *Marshaler) spdxAnnotations(c *core.Component, timeNow string) []spdx.Annotation { + var annotations []spdx.Annotation for _, p := range c.Properties { // Add properties that are not in other fields. if !slices.Contains(duplicateProperties, p.Name) { - texts = m.appendAttributionText(texts, p.Name, p.Value) + annotations = m.appendAnnotation(annotations, timeNow, p.Name, p.Value) } } - return texts + return annotations } func (m *Marshaler) spdxLicense(c *core.Component) string { diff --git a/pkg/sbom/spdx/marshal_test.go b/pkg/sbom/spdx/marshal_test.go index 74e9bee0a45d..4d9d33c013a7 100644 --- a/pkg/sbom/spdx/marshal_test.go +++ b/pkg/sbom/spdx/marshal_test.go @@ -25,6 +25,20 @@ import ( "github.com/aquasecurity/trivy/pkg/uuid" ) +func annotation(t *testing.T, comment string) spdx.Annotation { + t.Helper() + + return spdx.Annotation{ + AnnotationDate: "2021-08-25T12:20:30Z", + AnnotationType: spdx.CategoryOther, + Annotator: spdx.Annotator{ + Annotator: "trivy-0.56.2", + AnnotatorType: tspdx.PackageAnnotatorToolField, + }, + AnnotationComment: comment, + } +} + func TestMarshaler_Marshal(t *testing.T) { testCases := []struct { name string @@ -164,7 +178,7 @@ func TestMarshaler_Marshal(t *testing.T) { CreatorType: "Organization", }, { - Creator: "trivy-0.38.1", + Creator: "trivy-0.56.2", CreatorType: "Tool", }, }, @@ -176,9 +190,9 @@ func TestMarshaler_Marshal(t *testing.T) { PackageDownloadLocation: "NONE", PackageName: "app/Gemfile.lock", PrimaryPackagePurpose: tspdx.PackagePurposeApplication, - PackageAttributionTexts: []string{ - "Class: lang-pkgs", - "Type: bundler", + Annotations: []spdx.Annotation{ + annotation(t, "Class: lang-pkgs"), + annotation(t, "Type: bundler"), }, }, { @@ -186,9 +200,9 @@ func TestMarshaler_Marshal(t *testing.T) { PackageDownloadLocation: "NONE", PackageName: "app/subproject/Gemfile.lock", PrimaryPackagePurpose: tspdx.PackagePurposeApplication, - PackageAttributionTexts: []string{ - "Class: lang-pkgs", - "Type: bundler", + Annotations: []spdx.Annotation{ + annotation(t, "Class: lang-pkgs"), + annotation(t, "Type: bundler"), }, }, { @@ -202,14 +216,14 @@ func TestMarshaler_Marshal(t *testing.T) { Locator: "pkg:oci/rails@sha256%3Aa27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177?arch=arm64&repository_url=index.docker.io%2Flibrary%2Frails", }, }, - PackageAttributionTexts: []string{ - "DiffID: sha256:d871dadfb37b53ef1ca45be04fc527562b91989991a8f545345ae3be0b93f92a", - "ImageID: sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6", - "Labels:vendor: aquasecurity", - "RepoDigest: rails@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177", - "RepoTag: rails:latest", - "SchemaVersion: 2", - "Size: 1024", + Annotations: []spdx.Annotation{ + annotation(t, "DiffID: sha256:d871dadfb37b53ef1ca45be04fc527562b91989991a8f545345ae3be0b93f92a"), + annotation(t, "ImageID: sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6"), + annotation(t, "Labels:vendor: aquasecurity"), + annotation(t, "RepoDigest: rails@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177"), + annotation(t, "RepoTag: rails:latest"), + annotation(t, "SchemaVersion: 2"), + annotation(t, "Size: 1024"), }, PrimaryPackagePurpose: tspdx.PackagePurposeContainer, }, @@ -220,8 +234,8 @@ func TestMarshaler_Marshal(t *testing.T) { PackageVersion: "7.0.1", PackageLicenseConcluded: "NOASSERTION", PackageLicenseDeclared: "NOASSERTION", - PackageAttributionTexts: []string{ - "PkgType: bundler", + Annotations: []spdx.Annotation{ + annotation(t, "PkgType: bundler"), }, PackageExternalReferences: []*spdx.PackageExternalReference{ { @@ -241,8 +255,8 @@ func TestMarshaler_Marshal(t *testing.T) { PackageVersion: "7.0.1", PackageLicenseConcluded: "NOASSERTION", PackageLicenseDeclared: "NOASSERTION", - PackageAttributionTexts: []string{ - "PkgType: bundler", + Annotations: []spdx.Annotation{ + annotation(t, "PkgType: bundler"), }, PackageExternalReferences: []*spdx.PackageExternalReference{ { @@ -262,8 +276,8 @@ func TestMarshaler_Marshal(t *testing.T) { PackageVersion: "7.0.1", PackageLicenseConcluded: "NOASSERTION", PackageLicenseDeclared: "NOASSERTION", - PackageAttributionTexts: []string{ - "PkgType: bundler", + Annotations: []spdx.Annotation{ + annotation(t, "PkgType: bundler"), }, PackageExternalReferences: []*spdx.PackageExternalReference{ { @@ -283,8 +297,8 @@ func TestMarshaler_Marshal(t *testing.T) { PackageVersion: "2.30-93.el8", PackageLicenseConcluded: "GPL-3.0-or-later", PackageLicenseDeclared: "GPL-3.0-or-later", - PackageAttributionTexts: []string{ - "PkgType: centos", + Annotations: []spdx.Annotation{ + annotation(t, "PkgType: centos"), }, PackageSupplier: &spdx.Supplier{ SupplierType: tspdx.PackageSupplierOrganization, @@ -312,9 +326,9 @@ func TestMarshaler_Marshal(t *testing.T) { PackageName: "centos", PackageVersion: "8.3.2011", PrimaryPackagePurpose: tspdx.PackagePurposeOS, - PackageAttributionTexts: []string{ - "Class: os-pkgs", - "Type: centos", + Annotations: []spdx.Annotation{ + annotation(t, "Class: os-pkgs"), + annotation(t, "Type: centos"), }, }, }, @@ -486,7 +500,7 @@ func TestMarshaler_Marshal(t *testing.T) { CreatorType: "Organization", }, { - Creator: "trivy-0.38.1", + Creator: "trivy-0.56.2", CreatorType: "Tool", }, }, @@ -497,11 +511,11 @@ func TestMarshaler_Marshal(t *testing.T) { PackageName: "centos:latest", PackageSPDXIdentifier: "ContainerImage-413bfede37ad01fc", PackageDownloadLocation: "NONE", - PackageAttributionTexts: []string{ - "ImageID: sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6", - "RepoTag: centos:latest", - "SchemaVersion: 2", - "Size: 1024", + Annotations: []spdx.Annotation{ + annotation(t, "ImageID: sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6"), + annotation(t, "RepoTag: centos:latest"), + annotation(t, "SchemaVersion: 2"), + annotation(t, "Size: 1024"), }, PrimaryPackagePurpose: tspdx.PackagePurposeContainer, }, @@ -512,8 +526,8 @@ func TestMarshaler_Marshal(t *testing.T) { PackageVersion: "1:2.2.53-1.el8", PackageLicenseConcluded: "GPL-2.0-or-later", PackageLicenseDeclared: "GPL-2.0-or-later", - PackageAttributionTexts: []string{ - "PkgType: centos", + Annotations: []spdx.Annotation{ + annotation(t, "PkgType: centos"), }, PackageExternalReferences: []*spdx.PackageExternalReference{ { @@ -546,9 +560,9 @@ func TestMarshaler_Marshal(t *testing.T) { Locator: "pkg:gem/actionpack@7.0.1", }, }, - PackageAttributionTexts: []string{ - "LayerDiffID: sha256:ccb64cf0b7ba2e50741d0b64cae324eb5de3b1e2f580bbf177e721b67df38488", - "PkgType: gemspec", + Annotations: []spdx.Annotation{ + annotation(t, "LayerDiffID: sha256:ccb64cf0b7ba2e50741d0b64cae324eb5de3b1e2f580bbf177e721b67df38488"), + annotation(t, "PkgType: gemspec"), }, PrimaryPackagePurpose: tspdx.PackagePurposeLibrary, PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion}, @@ -571,9 +585,9 @@ func TestMarshaler_Marshal(t *testing.T) { Locator: "pkg:gem/actionpack@7.0.1", }, }, - PackageAttributionTexts: []string{ - "LayerDiffID: sha256:ccb64cf0b7ba2e50741d0b64cae324eb5de3b1e2f580bbf177e721b67df38488", - "PkgType: gemspec", + Annotations: []spdx.Annotation{ + annotation(t, "LayerDiffID: sha256:ccb64cf0b7ba2e50741d0b64cae324eb5de3b1e2f580bbf177e721b67df38488"), + annotation(t, "PkgType: gemspec"), }, PrimaryPackagePurpose: tspdx.PackagePurposeLibrary, PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion}, @@ -588,9 +602,9 @@ func TestMarshaler_Marshal(t *testing.T) { PackageName: "centos", PackageVersion: "8.3.2011", PrimaryPackagePurpose: tspdx.PackagePurposeOS, - PackageAttributionTexts: []string{ - "Class: os-pkgs", - "Type: centos", + Annotations: []spdx.Annotation{ + annotation(t, "Class: os-pkgs"), + annotation(t, "Type: centos"), }, }, }, @@ -719,7 +733,7 @@ func TestMarshaler_Marshal(t *testing.T) { CreatorType: "Organization", }, { - Creator: "trivy-0.38.1", + Creator: "trivy-0.56.2", CreatorType: "Tool", }, }, @@ -731,9 +745,9 @@ func TestMarshaler_Marshal(t *testing.T) { PackageDownloadLocation: "NONE", PackageName: "Gemfile.lock", PrimaryPackagePurpose: tspdx.PackagePurposeApplication, - PackageAttributionTexts: []string{ - "Class: lang-pkgs", - "Type: bundler", + Annotations: []spdx.Annotation{ + annotation(t, "Class: lang-pkgs"), + annotation(t, "Type: bundler"), }, }, { @@ -741,9 +755,9 @@ func TestMarshaler_Marshal(t *testing.T) { PackageDownloadLocation: "NONE", PackageName: "pom.xml", PrimaryPackagePurpose: tspdx.PackagePurposeApplication, - PackageAttributionTexts: []string{ - "Class: lang-pkgs", - "Type: pom", + Annotations: []spdx.Annotation{ + annotation(t, "Class: lang-pkgs"), + annotation(t, "Type: pom"), }, }, { @@ -763,8 +777,8 @@ func TestMarshaler_Marshal(t *testing.T) { PrimaryPackagePurpose: tspdx.PackagePurposeLibrary, PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion}, PackageSourceInfo: "package found in: Gemfile.lock", - PackageAttributionTexts: []string{ - "PkgType: bundler", + Annotations: []spdx.Annotation{ + annotation(t, "PkgType: bundler"), }, }, { @@ -784,17 +798,17 @@ func TestMarshaler_Marshal(t *testing.T) { PrimaryPackagePurpose: tspdx.PackagePurposeLibrary, PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion}, PackageSourceInfo: "package found in: pom.xml", - PackageAttributionTexts: []string{ - "PkgID: com.example:example:1.0.0", - "PkgType: pom", + Annotations: []spdx.Annotation{ + annotation(t, "PkgID: com.example:example:1.0.0"), + annotation(t, "PkgType: pom"), }, }, { PackageSPDXIdentifier: spdx.ElementID("Filesystem-5af0f1f08c20909a"), PackageDownloadLocation: "NONE", PackageName: "masahiro331/CVE-2021-41098", - PackageAttributionTexts: []string{ - "SchemaVersion: 2", + Annotations: []spdx.Annotation{ + annotation(t, "SchemaVersion: 2"), }, PrimaryPackagePurpose: tspdx.PackagePurposeSource, }, @@ -878,7 +892,7 @@ func TestMarshaler_Marshal(t *testing.T) { CreatorType: "Organization", }, { - Creator: "trivy-0.38.1", + Creator: "trivy-0.56.2", CreatorType: "Tool", }, }, @@ -906,16 +920,16 @@ func TestMarshaler_Marshal(t *testing.T) { }, PrimaryPackagePurpose: tspdx.PackagePurposeLibrary, PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion}, - PackageAttributionTexts: []string{ - "PkgType: jar", + Annotations: []spdx.Annotation{ + annotation(t, "PkgType: jar"), }, }, { PackageSPDXIdentifier: spdx.ElementID("Filesystem-121e7e7a43f02ab"), PackageDownloadLocation: "NONE", PackageName: "log4j-core-2.17.0.jar", - PackageAttributionTexts: []string{ - "SchemaVersion: 2", + Annotations: []spdx.Annotation{ + annotation(t, "SchemaVersion: 2"), }, PrimaryPackagePurpose: tspdx.PackagePurposeSource, }, @@ -980,7 +994,7 @@ func TestMarshaler_Marshal(t *testing.T) { CreatorType: "Organization", }, { - Creator: "trivy-0.38.1", + Creator: "trivy-0.56.2", CreatorType: "Tool", }, }, @@ -1001,9 +1015,9 @@ func TestMarshaler_Marshal(t *testing.T) { Locator: "pkg:npm/ruby-typeprof@0.20.1", }, }, - PackageAttributionTexts: []string{ - "LayerDiffID: sha256:661c3fd3cc16b34c070f3620ca6b03b6adac150f9a7e5d0e3c707a159990f88e", - "PkgType: node-pkg", + Annotations: []spdx.Annotation{ + annotation(t, "LayerDiffID: sha256:661c3fd3cc16b34c070f3620ca6b03b6adac150f9a7e5d0e3c707a159990f88e"), + annotation(t, "PkgType: node-pkg"), }, PrimaryPackagePurpose: tspdx.PackagePurposeLibrary, PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion}, @@ -1016,8 +1030,8 @@ func TestMarshaler_Marshal(t *testing.T) { PackageSPDXIdentifier: "Repository-1a78857c1a6a759e", PackageName: "http://test-aggregate", PackageDownloadLocation: "git+http://test-aggregate", - PackageAttributionTexts: []string{ - "SchemaVersion: 2", + Annotations: []spdx.Annotation{ + annotation(t, "SchemaVersion: 2"), }, PrimaryPackagePurpose: tspdx.PackagePurposeSource, }, @@ -1075,7 +1089,7 @@ func TestMarshaler_Marshal(t *testing.T) { CreatorType: "Organization", }, { - Creator: "trivy-0.38.1", + Creator: "trivy-0.56.2", CreatorType: "Tool", }, }, @@ -1086,8 +1100,8 @@ func TestMarshaler_Marshal(t *testing.T) { PackageName: "empty/path", PackageSPDXIdentifier: "Filesystem-70f34983067dba86", PackageDownloadLocation: "NONE", - PackageAttributionTexts: []string{ - "SchemaVersion: 2", + Annotations: []spdx.Annotation{ + annotation(t, "SchemaVersion: 2"), }, PrimaryPackagePurpose: tspdx.PackagePurposeSource, }, @@ -1137,7 +1151,7 @@ func TestMarshaler_Marshal(t *testing.T) { CreatorType: "Organization", }, { - Creator: "trivy-0.38.1", + Creator: "trivy-0.56.2", CreatorType: "Tool", }, }, @@ -1148,8 +1162,8 @@ func TestMarshaler_Marshal(t *testing.T) { PackageName: "secret", PackageSPDXIdentifier: "Filesystem-5c08d34162a2c5d3", PackageDownloadLocation: "NONE", - PackageAttributionTexts: []string{ - "SchemaVersion: 2", + Annotations: []spdx.Annotation{ + annotation(t, "SchemaVersion: 2"), }, PrimaryPackagePurpose: tspdx.PackagePurposeSource, }, @@ -1209,7 +1223,7 @@ func TestMarshaler_Marshal(t *testing.T) { CreatorType: "Organization", }, { - Creator: "trivy-0.38.1", + Creator: "trivy-0.56.2", CreatorType: "Tool", }, }, @@ -1221,9 +1235,9 @@ func TestMarshaler_Marshal(t *testing.T) { PackageDownloadLocation: "NONE", PackageName: "/usr/local/bin/test", PrimaryPackagePurpose: tspdx.PackagePurposeApplication, - PackageAttributionTexts: []string{ - "Class: lang-pkgs", - "Type: gobinary", + Annotations: []spdx.Annotation{ + annotation(t, "Class: lang-pkgs"), + annotation(t, "Type: gobinary"), }, }, { @@ -1235,8 +1249,8 @@ func TestMarshaler_Marshal(t *testing.T) { PrimaryPackagePurpose: tspdx.PackagePurposeLibrary, PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion}, PackageSourceInfo: "package found in: /usr/local/bin/test", - PackageAttributionTexts: []string{ - "PkgType: gobinary", + Annotations: []spdx.Annotation{ + annotation(t, "PkgType: gobinary"), }, }, { @@ -1256,16 +1270,16 @@ func TestMarshaler_Marshal(t *testing.T) { PrimaryPackagePurpose: tspdx.PackagePurposeLibrary, PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion}, PackageSourceInfo: "package found in: /usr/local/bin/test", - PackageAttributionTexts: []string{ - "PkgType: gobinary", + Annotations: []spdx.Annotation{ + annotation(t, "PkgType: gobinary"), }, }, { PackageName: "go-artifact", PackageSPDXIdentifier: "Filesystem-e340f27468b382be", PackageDownloadLocation: "NONE", - PackageAttributionTexts: []string{ - "SchemaVersion: 2", + Annotations: []spdx.Annotation{ + annotation(t, "SchemaVersion: 2"), }, PrimaryPackagePurpose: tspdx.PackagePurposeSource, }, @@ -1326,7 +1340,7 @@ func TestMarshaler_Marshal(t *testing.T) { ctx := clock.With(context.Background(), time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC)) uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d") - marshaler := tspdx.NewMarshaler("0.38.1", tspdx.WithHasher(hasher)) + marshaler := tspdx.NewMarshaler("0.56.2", tspdx.WithHasher(hasher)) spdxDoc, err := marshaler.MarshalReport(ctx, tc.inputReport) require.NoError(t, err) diff --git a/pkg/sbom/spdx/testdata/happy/bom.json b/pkg/sbom/spdx/testdata/happy/bom.json index 823c0471351f..88af63b3b71a 100644 --- a/pkg/sbom/spdx/testdata/happy/bom.json +++ b/pkg/sbom/spdx/testdata/happy/bom.json @@ -37,13 +37,43 @@ }, { "SPDXID": "SPDXRef-ContainerImage-b5d81cde5f95c8fc", - "attributionTexts": [ - "SchemaVersion: 2", - "ImageID: sha256:49193a2310dbad4c02382da87ac624a80a92387a4f7536235f9ba590e5bcd7b5", - "DiffID: sha256:dd565ff850e7003356e2b252758f9bdc1ff2803f61e995e24c7844f6297f8fc3", - "DiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1", - "RepoTag: maven-test-project:latest", - "RepoTag: tmp-test:latest" + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2024-10-29T06:50:38Z", + "annotationType": "OTHER", + "comment": "SchemaVersion: 2" + }, + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2024-10-29T06:50:38Z", + "annotationType": "OTHER", + "comment": "ImageID: sha256:49193a2310dbad4c02382da87ac624a80a92387a4f7536235f9ba590e5bcd7b5" + }, + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2024-10-29T06:50:38Z", + "annotationType": "OTHER", + "comment": "DiffID: sha256:dd565ff850e7003356e2b252758f9bdc1ff2803f61e995e24c7844f6297f8fc3" + }, + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2024-10-29T06:50:38Z", + "annotationType": "OTHER", + "comment": "DiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1" + }, + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2024-10-29T06:50:38Z", + "annotationType": "OTHER", + "comment": "RepoTag: maven-test-project:latest" + }, + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2024-10-29T06:50:38Z", + "annotationType": "OTHER", + "comment": "RepoTag: tmp-test:latest" + } ], "filesAnalyzed": false, "name": "meven-test-project" @@ -56,8 +86,13 @@ }, { "SPDXID": "SPDXRef-Package-2906575950df652b", - "attributionTexts": [ - "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1" + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2024-10-29T06:50:38Z", + "annotationType": "OTHER", + "comment": "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1" + } ], "externalRefs": [ { @@ -74,8 +109,13 @@ }, { "SPDXID": "SPDXRef-Package-2a53baa495b9ddaf", - "attributionTexts": [ - "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1" + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2024-10-29T06:50:38Z", + "annotationType": "OTHER", + "comment": "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1" + } ], "externalRefs": [ { @@ -92,8 +132,13 @@ }, { "SPDXID": "SPDXRef-Package-5e2e255ac76747ef", - "attributionTexts": [ - "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1" + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2024-10-29T06:50:38Z", + "annotationType": "OTHER", + "comment": "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1" + } ], "externalRefs": [ { @@ -110,8 +155,13 @@ }, { "SPDXID": "SPDXRef-Package-5f1dbaff8de5eb06", - "attributionTexts": [ - "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1" + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2024-10-29T06:50:38Z", + "annotationType": "OTHER", + "comment": "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1" + } ], "externalRefs": [ { @@ -128,8 +178,13 @@ }, { "SPDXID": "SPDXRef-Package-84ebffe38343d949", - "attributionTexts": [ - "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1" + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2024-10-29T06:50:38Z", + "annotationType": "OTHER", + "comment": "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1" + } ], "externalRefs": [ { @@ -146,8 +201,13 @@ }, { "SPDXID": "SPDXRef-Package-b7ebaf0233f1ef7b", - "attributionTexts": [ - "LayerDiffID: sha256:dd565ff850e7003356e2b252758f9bdc1ff2803f61e995e24c7844f6297f8fc3" + "annotations": [ + { + "annotator": "Tool: trivy-dev", + "annotationDate": "2024-10-29T06:50:38Z", + "annotationType": "OTHER", + "comment": "LayerDiffID: sha256:dd565ff850e7003356e2b252758f9bdc1ff2803f61e995e24c7844f6297f8fc3" + } ], "externalRefs": [ { diff --git a/pkg/sbom/spdx/unmarshal.go b/pkg/sbom/spdx/unmarshal.go index d2ba05b44999..c7ed6b0905dd 100644 --- a/pkg/sbom/spdx/unmarshal.go +++ b/pkg/sbom/spdx/unmarshal.go @@ -194,9 +194,21 @@ func (s *SPDX) parsePackage(spdxPkg spdx.Package) (*core.Component, error) { } } - // Attributions - for _, attr := range spdxPkg.PackageAttributionTexts { - k, v, ok := strings.Cut(attr, ": ") + // Trivy stores properties in Annotations + // But previous versions stored properties in AttributionTexts + // So we need to check both cases to maintain backward compatibility + var props []string + if len(spdxPkg.Annotations) > 0 { + for _, annotation := range spdxPkg.Annotations { + props = append(props, annotation.AnnotationComment) + } + } else if len(spdxPkg.PackageAttributionTexts) > 0 { + for _, attr := range spdxPkg.PackageAttributionTexts { + props = append(props, attr) + } + } + for _, prop := range props { + k, v, ok := strings.Cut(prop, ": ") if !ok { continue } From 78827768a612ab305bf9c55409ce76d6774302a5 Mon Sep 17 00:00:00 2001 From: afdesk Date: Thu, 31 Oct 2024 07:14:56 +0600 Subject: [PATCH 75/94] fix(k8s): skip resources without misconfigs (#7797) --- pkg/k8s/report/report.go | 11 ++++++++++- pkg/k8s/report/report_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/pkg/k8s/report/report.go b/pkg/k8s/report/report.go index b52391ec8239..947d39de14b8 100644 --- a/pkg/k8s/report/report.go +++ b/pkg/k8s/report/report.go @@ -90,8 +90,13 @@ func (r Report) consolidate() ConsolidatedReport { for _, m := range r.Resources { if vulnerabilitiesOrSecretResource(m) { vulnerabilities = append(vulnerabilities, m) - } else { + } + if misconfigsResource(m) { + res, ok := index[m.fullname()] index[m.fullname()] = m + if ok { + index[m.fullname()].Results[0].Misconfigurations = append(index[m.fullname()].Results[0].Misconfigurations, res.Results[0].Misconfigurations...) + } } } @@ -278,6 +283,10 @@ func vulnerabilitiesOrSecretResource(resource Resource) bool { return len(resource.Results) > 0 && (len(resource.Results[0].Vulnerabilities) > 0 || len(resource.Results[0].Secrets) > 0) } +func misconfigsResource(resource Resource) bool { + return len(resource.Results) > 0 && len(resource.Results[0].Misconfigurations) > 0 +} + func nodeKind(resource Resource) Resource { if nodeInfoResource(resource) { resource.Kind = "Node" diff --git a/pkg/k8s/report/report_test.go b/pkg/k8s/report/report_test.go index 1a984eb71b23..9ba663dc4783 100644 --- a/pkg/k8s/report/report_test.go +++ b/pkg/k8s/report/report_test.go @@ -119,6 +119,23 @@ var ( }, } + orionDeployWithAnotherMisconfig = Resource{ + Namespace: "default", + Kind: "Deploy", + Name: "orion", + Results: types.Results{ + { + Misconfigurations: []types.DetectedMisconfiguration{ + { + ID: "ID201", + Status: types.MisconfStatusFailure, + Severity: "HIGH", + }, + }, + }, + }, + } + image1WithVulns = Resource{ Namespace: "default", Kind: "Pod", @@ -424,6 +441,10 @@ var ( ) func TestReport_consolidate(t *testing.T) { + concatenatedResource := orionDeployWithAnotherMisconfig + concatenatedResource.Results[0].Misconfigurations = append(concatenatedResource.Results[0].Misconfigurations, + deployOrionWithMisconfigs.Results[0].Misconfigurations...) + tests := []struct { name string report Report @@ -471,6 +492,18 @@ func TestReport_consolidate(t *testing.T) { "default/cronjob/hello": cronjobHelloWithVulns, }, }, + { + name: "report with misconfigs in image and pod", + report: Report{ + Resources: []Resource{ + deployOrionWithMisconfigs, + orionDeployWithAnotherMisconfig, + }, + }, + expectedFindings: map[string]Resource{ + "default/deploy/orion": concatenatedResource, + }, + }, { name: "report with multi image pod containing vulnerabilities", report: Report{ From e872ec006c0745a5a142728af0096c6d6bb9ddf3 Mon Sep 17 00:00:00 2001 From: Rutam Prita Mishra Date: Thu, 31 Oct 2024 11:33:22 +0530 Subject: [PATCH 76/94] fix(go): Do not trim v prefix from versions in Go Mod Analyzer (#7733) Co-authored-by: DmitriyLewen --- docs/docs/supply-chain/vex/file.md | 8 +- .../testdata/fixtures/vex/file/openvex.json | 2 +- integration/testdata/gomod-skip.json.golden | 24 +- integration/testdata/gomod-vex.json.golden | 24 +- integration/testdata/gomod.json.golden | 30 +- pkg/dependency/id_test.go | 2 +- pkg/dependency/parser/golang/binary/parse.go | 3 + .../parser/golang/binary/parse_test.go | 10 +- pkg/dependency/parser/golang/mod/parse.go | 25 +- .../parser/golang/mod/parse_testcase.go | 48 +- pkg/dependency/parser/golang/sum/parse.go | 2 +- .../parser/golang/sum/parse_testcase.go | 704 +++++++++--------- .../language/golang/binary/binary_test.go | 2 +- pkg/fanal/analyzer/language/golang/mod/mod.go | 2 +- .../analyzer/language/golang/mod/mod_test.go | 12 +- pkg/purl/purl_test.go | 20 +- pkg/result/filter_test.go | 14 +- pkg/result/testdata/openvex.json | 2 +- pkg/sbom/io/encode_test.go | 32 +- pkg/vex/testdata/csaf-relationships.json | 4 +- pkg/vex/testdata/csaf.json | 2 +- pkg/vex/testdata/openvex-nested.json | 4 +- pkg/vex/vex_test.go | 40 +- 23 files changed, 510 insertions(+), 506 deletions(-) diff --git a/docs/docs/supply-chain/vex/file.md b/docs/docs/supply-chain/vex/file.md index 7c847ec49e14..242ec4c5a040 100644 --- a/docs/docs/supply-chain/vex/file.md +++ b/docs/docs/supply-chain/vex/file.md @@ -64,7 +64,7 @@ $ cat < trivy.vex.cdx }, "affects": [ { - "ref": "urn:cdx:3e671687-395b-41f5-a30f-a58921a69b79/1#pkg:golang/github.com/aws/aws-sdk-go@1.44.234" + "ref": "urn:cdx:3e671687-395b-41f5-a30f-a58921a69b79/1#pkg:golang/github.com/aws/aws-sdk-go@v1.44.234" } ] } @@ -115,7 +115,7 @@ Total: 1 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 0, CRITICAL: 0) ┌───────────────────────────┬───────────────┬──────────┬───────────────────┬───────────────┬────────────────────────────────────────────────────────────┐ │ Library │ Vulnerability │ Severity │ Installed Version │ Fixed Version │ Title │ ├───────────────────────────┼───────────────┼──────────┼───────────────────┼───────────────┼────────────────────────────────────────────────────────────┤ -│ github.com/aws/aws-sdk-go │ CVE-2020-8912 │ LOW │ 1.44.234 │ │ aws-sdk-go: In-band key negotiation issue in AWS S3 Crypto │ +│ github.com/aws/aws-sdk-go │ CVE-2020-8912 │ LOW │ v1.44.234 │ │ aws-sdk-go: In-band key negotiation issue in AWS S3 Crypto │ │ │ │ │ │ │ SDK for golang... │ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2020-8912 │ └───────────────────────────┴───────────────┴──────────┴───────────────────┴───────────────┴────────────────────────────────────────────────────────────┘ @@ -497,9 +497,9 @@ Now, suppose a VEX statement is issued for `Module B` as follows: "vulnerability": {"name": "CVE-XXXX-YYYY"}, "products": [ { - "@id": "pkg:golang/module-b@1.0.0", + "@id": "pkg:golang/module-b@v1.0.0", "subcomponents": [ - { "@id": "pkg:golang/module-c@2.0.0" } + { "@id": "pkg:golang/module-c@v2.0.0" } ] } ], diff --git a/integration/testdata/fixtures/vex/file/openvex.json b/integration/testdata/fixtures/vex/file/openvex.json index 38773ba57694..9782e1716387 100644 --- a/integration/testdata/fixtures/vex/file/openvex.json +++ b/integration/testdata/fixtures/vex/file/openvex.json @@ -11,7 +11,7 @@ { "@id": "pkg:golang/github.com/testdata/testdata", "subcomponents": [ - { "@id": "pkg:golang/github.com/open-policy-agent/opa@0.35.0" } + { "@id": "pkg:golang/github.com/open-policy-agent/opa@v0.35.0" } ] } ], diff --git a/integration/testdata/gomod-skip.json.golden b/integration/testdata/gomod-skip.json.golden index 69ab998ec9dd..877fd627b89a 100644 --- a/integration/testdata/gomod-skip.json.golden +++ b/integration/testdata/gomod-skip.json.golden @@ -26,10 +26,10 @@ "PkgID": "github.com/docker/distribution@v2.7.1+incompatible", "PkgName": "github.com/docker/distribution", "PkgIdentifier": { - "PURL": "pkg:golang/github.com/docker/distribution@2.7.1%2Bincompatible", - "UID": "de19cd663ca047a8" + "PURL": "pkg:golang/github.com/docker/distribution@v2.7.1%2Bincompatible", + "UID": "9d949a7b01249e68" }, - "InstalledVersion": "2.7.1+incompatible", + "InstalledVersion": "v2.7.1+incompatible", "FixedVersion": "v2.8.0", "Status": "fixed", "Layer": {}, @@ -53,10 +53,10 @@ "PkgID": "github.com/open-policy-agent/opa@v0.35.0", "PkgName": "github.com/open-policy-agent/opa", "PkgIdentifier": { - "PURL": "pkg:golang/github.com/open-policy-agent/opa@0.35.0", - "UID": "6b685002e082ffc5" + "PURL": "pkg:golang/github.com/open-policy-agent/opa@v0.35.0", + "UID": "e89e2b0d8977e2a" }, - "InstalledVersion": "0.35.0", + "InstalledVersion": "v0.35.0", "FixedVersion": "0.37.0", "Status": "fixed", "Layer": {}, @@ -100,10 +100,10 @@ "PkgID": "golang.org/x/text@v0.3.6", "PkgName": "golang.org/x/text", "PkgIdentifier": { - "PURL": "pkg:golang/golang.org/x/text@0.3.6", - "UID": "825dc613c0f39d45" + "PURL": "pkg:golang/golang.org/x/text@v0.3.6", + "UID": "3050088ce9eb2ce4" }, - "InstalledVersion": "0.3.6", + "InstalledVersion": "v0.3.6", "FixedVersion": "0.3.7", "Status": "fixed", "Layer": {}, @@ -133,10 +133,10 @@ "PkgID": "github.com/docker/distribution@v2.7.1+incompatible", "PkgName": "github.com/docker/distribution", "PkgIdentifier": { - "PURL": "pkg:golang/github.com/docker/distribution@2.7.1%2Bincompatible", - "UID": "94376dc37054a7e8" + "PURL": "pkg:golang/github.com/docker/distribution@v2.7.1%2Bincompatible", + "UID": "2f7f0fa81860b8f1" }, - "InstalledVersion": "2.7.1+incompatible", + "InstalledVersion": "v2.7.1+incompatible", "FixedVersion": "v2.8.0", "Status": "fixed", "Layer": {}, diff --git a/integration/testdata/gomod-vex.json.golden b/integration/testdata/gomod-vex.json.golden index a2269bd1d0b7..34d96dc0ce95 100644 --- a/integration/testdata/gomod-vex.json.golden +++ b/integration/testdata/gomod-vex.json.golden @@ -26,10 +26,10 @@ "PkgID": "github.com/docker/distribution@v2.7.1+incompatible", "PkgName": "github.com/docker/distribution", "PkgIdentifier": { - "PURL": "pkg:golang/github.com/docker/distribution@2.7.1%2Bincompatible", - "UID": "de19cd663ca047a8" + "PURL": "pkg:golang/github.com/docker/distribution@v2.7.1%2Bincompatible", + "UID": "9d949a7b01249e68" }, - "InstalledVersion": "2.7.1+incompatible", + "InstalledVersion": "v2.7.1+incompatible", "FixedVersion": "v2.8.0", "Status": "fixed", "Layer": {}, @@ -53,10 +53,10 @@ "PkgID": "golang.org/x/text@v0.3.6", "PkgName": "golang.org/x/text", "PkgIdentifier": { - "PURL": "pkg:golang/golang.org/x/text@0.3.6", - "UID": "825dc613c0f39d45" + "PURL": "pkg:golang/golang.org/x/text@v0.3.6", + "UID": "3050088ce9eb2ce4" }, - "InstalledVersion": "0.3.6", + "InstalledVersion": "v0.3.6", "FixedVersion": "0.3.7", "Status": "fixed", "Layer": {}, @@ -86,10 +86,10 @@ "PkgID": "github.com/docker/distribution@v2.7.1+incompatible", "PkgName": "github.com/docker/distribution", "PkgIdentifier": { - "PURL": "pkg:golang/github.com/docker/distribution@2.7.1%2Bincompatible", - "UID": "94376dc37054a7e8" + "PURL": "pkg:golang/github.com/docker/distribution@v2.7.1%2Bincompatible", + "UID": "2f7f0fa81860b8f1" }, - "InstalledVersion": "2.7.1+incompatible", + "InstalledVersion": "v2.7.1+incompatible", "FixedVersion": "v2.8.0", "Status": "fixed", "Layer": {}, @@ -120,10 +120,10 @@ "PkgID": "github.com/docker/distribution@v2.7.1+incompatible", "PkgName": "github.com/docker/distribution", "PkgIdentifier": { - "PURL": "pkg:golang/github.com/docker/distribution@2.7.1%2Bincompatible", - "UID": "94306cdcf85fb50a" + "PURL": "pkg:golang/github.com/docker/distribution@v2.7.1%2Bincompatible", + "UID": "3ad40723ed2fce22" }, - "InstalledVersion": "2.7.1+incompatible", + "InstalledVersion": "v2.7.1+incompatible", "FixedVersion": "v2.8.0", "Status": "fixed", "Layer": {}, diff --git a/integration/testdata/gomod.json.golden b/integration/testdata/gomod.json.golden index 627088188285..551b787cadd6 100644 --- a/integration/testdata/gomod.json.golden +++ b/integration/testdata/gomod.json.golden @@ -26,10 +26,10 @@ "PkgID": "github.com/docker/distribution@v2.7.1+incompatible", "PkgName": "github.com/docker/distribution", "PkgIdentifier": { - "PURL": "pkg:golang/github.com/docker/distribution@2.7.1%2Bincompatible", - "UID": "de19cd663ca047a8" + "PURL": "pkg:golang/github.com/docker/distribution@v2.7.1%2Bincompatible", + "UID": "9d949a7b01249e68" }, - "InstalledVersion": "2.7.1+incompatible", + "InstalledVersion": "v2.7.1+incompatible", "FixedVersion": "v2.8.0", "Status": "fixed", "Layer": {}, @@ -53,10 +53,10 @@ "PkgID": "github.com/open-policy-agent/opa@v0.35.0", "PkgName": "github.com/open-policy-agent/opa", "PkgIdentifier": { - "PURL": "pkg:golang/github.com/open-policy-agent/opa@0.35.0", - "UID": "6b685002e082ffc5" + "PURL": "pkg:golang/github.com/open-policy-agent/opa@v0.35.0", + "UID": "e89e2b0d8977e2a" }, - "InstalledVersion": "0.35.0", + "InstalledVersion": "v0.35.0", "FixedVersion": "0.37.0", "Status": "fixed", "Layer": {}, @@ -100,10 +100,10 @@ "PkgID": "golang.org/x/text@v0.3.6", "PkgName": "golang.org/x/text", "PkgIdentifier": { - "PURL": "pkg:golang/golang.org/x/text@0.3.6", - "UID": "825dc613c0f39d45" + "PURL": "pkg:golang/golang.org/x/text@v0.3.6", + "UID": "3050088ce9eb2ce4" }, - "InstalledVersion": "0.3.6", + "InstalledVersion": "v0.3.6", "FixedVersion": "0.3.7", "Status": "fixed", "Layer": {}, @@ -133,10 +133,10 @@ "PkgID": "github.com/docker/distribution@v2.7.1+incompatible", "PkgName": "github.com/docker/distribution", "PkgIdentifier": { - "PURL": "pkg:golang/github.com/docker/distribution@2.7.1%2Bincompatible", - "UID": "94376dc37054a7e8" + "PURL": "pkg:golang/github.com/docker/distribution@v2.7.1%2Bincompatible", + "UID": "2f7f0fa81860b8f1" }, - "InstalledVersion": "2.7.1+incompatible", + "InstalledVersion": "v2.7.1+incompatible", "FixedVersion": "v2.8.0", "Status": "fixed", "Layer": {}, @@ -167,10 +167,10 @@ "PkgID": "github.com/docker/distribution@v2.7.1+incompatible", "PkgName": "github.com/docker/distribution", "PkgIdentifier": { - "PURL": "pkg:golang/github.com/docker/distribution@2.7.1%2Bincompatible", - "UID": "94306cdcf85fb50a" + "PURL": "pkg:golang/github.com/docker/distribution@v2.7.1%2Bincompatible", + "UID": "3ad40723ed2fce22" }, - "InstalledVersion": "2.7.1+incompatible", + "InstalledVersion": "v2.7.1+incompatible", "FixedVersion": "v2.8.0", "Status": "fixed", "Layer": {}, diff --git a/pkg/dependency/id_test.go b/pkg/dependency/id_test.go index 18359f771e7b..2b8c0e4a71b1 100644 --- a/pkg/dependency/id_test.go +++ b/pkg/dependency/id_test.go @@ -34,7 +34,7 @@ func TestID(t *testing.T) { args: args{ ltype: types.GoModule, name: "test", - version: "1.0.0", + version: "v1.0.0", }, want: "test@v1.0.0", }, diff --git a/pkg/dependency/parser/golang/binary/parse.go b/pkg/dependency/parser/golang/binary/parse.go index 6959e0ede5fa..2a7a2a128de7 100644 --- a/pkg/dependency/parser/golang/binary/parse.go +++ b/pkg/dependency/parser/golang/binary/parse.go @@ -3,6 +3,7 @@ package binary import ( "cmp" "debug/buildinfo" + "fmt" "runtime/debug" "slices" "sort" @@ -56,6 +57,8 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc // Ex: "go1.22.3 X:boringcrypto" stdlibVersion := strings.TrimPrefix(info.GoVersion, "go") stdlibVersion, _, _ = strings.Cut(stdlibVersion, " ") + // Add the `v` prefix to be consistent with module and dependency versions. + stdlibVersion = fmt.Sprintf("v%s", stdlibVersion) ldflags := p.ldFlags(info.Settings) pkgs := make(ftypes.Packages, 0, len(info.Deps)+2) diff --git a/pkg/dependency/parser/golang/binary/parse_test.go b/pkg/dependency/parser/golang/binary/parse_test.go index 2fbb6acff7b2..aade2a32cf24 100644 --- a/pkg/dependency/parser/golang/binary/parse_test.go +++ b/pkg/dependency/parser/golang/binary/parse_test.go @@ -20,7 +20,7 @@ func TestParse(t *testing.T) { }, { Name: "stdlib", - Version: "1.15.2", + Version: "v1.15.2", Relationship: ftypes.RelationshipDirect, }, { @@ -69,7 +69,7 @@ func TestParse(t *testing.T) { }, { Name: "stdlib", - Version: "1.16.4", + Version: "v1.16.4", Relationship: ftypes.RelationshipDirect, }, { @@ -93,7 +93,7 @@ func TestParse(t *testing.T) { }, { Name: "stdlib", - Version: "1.20.6", + Version: "v1.20.6", Relationship: ftypes.RelationshipDirect, }, }, @@ -109,7 +109,7 @@ func TestParse(t *testing.T) { }, { Name: "stdlib", - Version: "1.22.1", + Version: "v1.22.1", Relationship: ftypes.RelationshipDirect, }, }, @@ -120,7 +120,7 @@ func TestParse(t *testing.T) { want: []ftypes.Package{ { Name: "stdlib", - Version: "1.22.1", + Version: "v1.22.1", Relationship: ftypes.RelationshipDirect, }, }, diff --git a/pkg/dependency/parser/golang/mod/parse.go b/pkg/dependency/parser/golang/mod/parse.go index bbf42926a766..ddcd2ccc880e 100644 --- a/pkg/dependency/parser/golang/mod/parse.go +++ b/pkg/dependency/parser/golang/mod/parse.go @@ -1,6 +1,7 @@ package mod import ( + "fmt" "io" "regexp" "strconv" @@ -90,9 +91,11 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc if p.useMinVersion { if toolchainVer := toolchainVersion(modFileParsed.Toolchain, modFileParsed.Go); toolchainVer != "" { pkgs["stdlib"] = ftypes.Package{ - ID: packageID("stdlib", toolchainVer), - Name: "stdlib", - Version: toolchainVer, + ID: packageID("stdlib", toolchainVer), + Name: "stdlib", + // Our versioning library doesn't support canonical (goX.Y.Z) format, + // So we need to add `v` prefix for consistency (with module and dependency versions). + Version: fmt.Sprintf("v%s", toolchainVer), Relationship: ftypes.RelationshipDirect, // Considered a direct dependency as the main module depends on the standard packages. } } @@ -100,11 +103,10 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc // Main module if m := modFileParsed.Module; m != nil { - ver := strings.TrimPrefix(m.Mod.Version, "v") pkgs[m.Mod.Path] = ftypes.Package{ - ID: packageID(m.Mod.Path, ver), + ID: packageID(m.Mod.Path, m.Mod.Version), Name: m.Mod.Path, - Version: ver, + Version: m.Mod.Version, ExternalReferences: p.GetExternalRefs(m.Mod.Path), Relationship: ftypes.RelationshipRoot, } @@ -116,11 +118,10 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc if skipIndirect && require.Indirect { continue } - ver := strings.TrimPrefix(require.Mod.Version, "v") pkgs[require.Mod.Path] = ftypes.Package{ - ID: packageID(require.Mod.Path, ver), + ID: packageID(require.Mod.Path, require.Mod.Version), Name: require.Mod.Path, - Version: ver, + Version: require.Mod.Version, Relationship: lo.Ternary(require.Indirect, ftypes.RelationshipIndirect, ftypes.RelationshipDirect), ExternalReferences: p.GetExternalRefs(require.Mod.Path), } @@ -136,7 +137,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc } // If the replace directive has a version on the left side, make sure it matches the version that was imported. - if rep.Old.Version != "" && old.Version != rep.Old.Version[1:] { + if rep.Old.Version != "" && old.Version != rep.Old.Version { continue } @@ -153,9 +154,9 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc // Add replaced package to package register. pkgs[rep.New.Path] = ftypes.Package{ - ID: packageID(rep.New.Path, rep.New.Version[1:]), + ID: packageID(rep.New.Path, rep.New.Version), Name: rep.New.Path, - Version: rep.New.Version[1:], + Version: rep.New.Version, Relationship: old.Relationship, ExternalReferences: p.GetExternalRefs(rep.New.Path), } diff --git a/pkg/dependency/parser/golang/mod/parse_testcase.go b/pkg/dependency/parser/golang/mod/parse_testcase.go index 4671ef3e6854..b8ed49008926 100644 --- a/pkg/dependency/parser/golang/mod/parse_testcase.go +++ b/pkg/dependency/parser/golang/mod/parse_testcase.go @@ -23,13 +23,13 @@ var ( { ID: "stdlib@v1.22.5", Name: "stdlib", - Version: "1.22.5", + Version: "v1.22.5", Relationship: ftypes.RelationshipDirect, }, { ID: "github.com/aquasecurity/go-version@v0.0.0-20240603093900-cf8a8d29271d", Name: "github.com/aquasecurity/go-version", - Version: "0.0.0-20240603093900-cf8a8d29271d", + Version: "v0.0.0-20240603093900-cf8a8d29271d", Relationship: ftypes.RelationshipDirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -41,7 +41,7 @@ var ( { ID: "github.com/davecgh/go-spew@v1.1.2-0.20180830191138-d8f796af33cc", Name: "github.com/davecgh/go-spew", - Version: "1.1.2-0.20180830191138-d8f796af33cc", + Version: "v1.1.2-0.20180830191138-d8f796af33cc", Relationship: ftypes.RelationshipIndirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -53,7 +53,7 @@ var ( { ID: "github.com/pmezard/go-difflib@v1.0.1-0.20181226105442-5d4384ee4fb2", Name: "github.com/pmezard/go-difflib", - Version: "1.0.1-0.20181226105442-5d4384ee4fb2", + Version: "v1.0.1-0.20181226105442-5d4384ee4fb2", Relationship: ftypes.RelationshipIndirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -65,7 +65,7 @@ var ( { ID: "github.com/stretchr/testify@v1.9.0", Name: "github.com/stretchr/testify", - Version: "1.9.0", + Version: "v1.9.0", Relationship: ftypes.RelationshipIndirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -77,7 +77,7 @@ var ( { ID: "golang.org/x/xerrors@v0.0.0-20231012003039-104605ab7028", Name: "golang.org/x/xerrors", - Version: "0.0.0-20231012003039-104605ab7028", + Version: "v0.0.0-20231012003039-104605ab7028", Relationship: ftypes.RelationshipIndirect, }, } @@ -102,7 +102,7 @@ var ( { ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20220406074731-71021a481237", Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20220406074731-71021a481237", + Version: "v0.0.0-20220406074731-71021a481237", Relationship: ftypes.RelationshipDirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -114,7 +114,7 @@ var ( { ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", Name: "golang.org/x/xerrors", - Version: "0.0.0-20200804184101-5ec99f83aff1", + Version: "v0.0.0-20200804184101-5ec99f83aff1", Relationship: ftypes.RelationshipIndirect, }, } @@ -135,7 +135,7 @@ var ( { ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211110174639-8257534ffed3", Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20211110174639-8257534ffed3", + Version: "v0.0.0-20211110174639-8257534ffed3", Relationship: ftypes.RelationshipDirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -147,7 +147,7 @@ var ( { ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", Name: "golang.org/x/xerrors", - Version: "0.0.0-20200804184101-5ec99f83aff1", + Version: "v0.0.0-20200804184101-5ec99f83aff1", Relationship: ftypes.RelationshipIndirect, }, } @@ -168,7 +168,7 @@ var ( { ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20220406074731-71021a481237", Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20220406074731-71021a481237", + Version: "v0.0.0-20220406074731-71021a481237", Relationship: ftypes.RelationshipDirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -180,7 +180,7 @@ var ( { ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", Name: "golang.org/x/xerrors", - Version: "0.0.0-20200804184101-5ec99f83aff1", + Version: "v0.0.0-20200804184101-5ec99f83aff1", Relationship: ftypes.RelationshipIndirect, }, } @@ -201,7 +201,7 @@ var ( { ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff", Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20211224170007-df43bca6b6ff", + Version: "v0.0.0-20211224170007-df43bca6b6ff", Relationship: ftypes.RelationshipDirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -213,13 +213,13 @@ var ( { ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", Name: "golang.org/x/xerrors", - Version: "0.0.0-20200804184101-5ec99f83aff1", + Version: "v0.0.0-20200804184101-5ec99f83aff1", Relationship: ftypes.RelationshipIndirect, }, { ID: "gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b", Name: "gopkg.in/yaml.v3", - Version: "3.0.0-20210107192922-496545a6307b", + Version: "v3.0.0-20210107192922-496545a6307b", Relationship: ftypes.RelationshipIndirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -246,7 +246,7 @@ var ( { ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff", Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20211224170007-df43bca6b6ff", + Version: "v0.0.0-20211224170007-df43bca6b6ff", Relationship: ftypes.RelationshipDirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -258,7 +258,7 @@ var ( { ID: "gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b", Name: "gopkg.in/yaml.v3", - Version: "3.0.0-20210107192922-496545a6307b", + Version: "v3.0.0-20210107192922-496545a6307b", Relationship: ftypes.RelationshipIndirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -285,7 +285,7 @@ var ( { ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff", Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20211224170007-df43bca6b6ff", + Version: "v0.0.0-20211224170007-df43bca6b6ff", Relationship: ftypes.RelationshipDirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -297,7 +297,7 @@ var ( { ID: "gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b", Name: "gopkg.in/yaml.v3", - Version: "3.0.0-20210107192922-496545a6307b", + Version: "v3.0.0-20210107192922-496545a6307b", Relationship: ftypes.RelationshipIndirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -324,7 +324,7 @@ var ( { ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff", Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20211224170007-df43bca6b6ff", + Version: "v0.0.0-20211224170007-df43bca6b6ff", Relationship: ftypes.RelationshipDirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -336,13 +336,13 @@ var ( { ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", Name: "golang.org/x/xerrors", - Version: "0.0.0-20200804184101-5ec99f83aff1", + Version: "v0.0.0-20200804184101-5ec99f83aff1", Relationship: ftypes.RelationshipIndirect, }, { ID: "gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b", Name: "gopkg.in/yaml.v3", - Version: "3.0.0-20210107192922-496545a6307b", + Version: "v3.0.0-20210107192922-496545a6307b", Relationship: ftypes.RelationshipIndirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -369,7 +369,7 @@ var ( { ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff", Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20211224170007-df43bca6b6ff", + Version: "v0.0.0-20211224170007-df43bca6b6ff", Relationship: ftypes.RelationshipDirect, ExternalReferences: []ftypes.ExternalRef{ { @@ -396,7 +396,7 @@ var ( { ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff", Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20211224170007-df43bca6b6ff", + Version: "v0.0.0-20211224170007-df43bca6b6ff", Relationship: ftypes.RelationshipDirect, ExternalReferences: []ftypes.ExternalRef{ { diff --git a/pkg/dependency/parser/golang/sum/parse.go b/pkg/dependency/parser/golang/sum/parse.go index 4ec742b1bae2..8362a808c036 100644 --- a/pkg/dependency/parser/golang/sum/parse.go +++ b/pkg/dependency/parser/golang/sum/parse.go @@ -32,7 +32,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc // go.sum records and sorts all non-major versions // with the latest version as last entry - uniquePkgs[s[0]] = strings.TrimSuffix(strings.TrimPrefix(s[1], "v"), "/go.mod") + uniquePkgs[s[0]] = strings.TrimSuffix(s[1], "/go.mod") } if err := scanner.Err(); err != nil { return nil, nil, xerrors.Errorf("scan error: %w", err) diff --git a/pkg/dependency/parser/golang/sum/parse_testcase.go b/pkg/dependency/parser/golang/sum/parse_testcase.go index fc607de86e2a..532a241b1ccc 100644 --- a/pkg/dependency/parser/golang/sum/parse_testcase.go +++ b/pkg/dependency/parser/golang/sum/parse_testcase.go @@ -11,13 +11,13 @@ var ( // go get golang.org/x/xerrors // go list -m all | awk 'NR>1 {sub(/^v/, "", $2); printf("{\""$1"\", \""$2"\", },\n")}' GoModNormal = []ftypes.Package{ - {Name: "golang.org/x/xerrors", Version: "0.0.0-20200804184101-5ec99f83aff1"}, + {Name: "golang.org/x/xerrors", Version: "v0.0.0-20200804184101-5ec99f83aff1"}, } // https://github.com/uudashr/gopkgs/blob/616744904701ef01d868da4b66aad0e6856c361d/v2/go.sum GoModEmptyLine = []ftypes.Package{ - {Name: "github.com/karrick/godirwalk", Version: "1.12.0"}, - {Name: "github.com/pkg/errors", Version: "0.8.1"}, + {Name: "github.com/karrick/godirwalk", Version: "v1.12.0"}, + {Name: "github.com/pkg/errors", Version: "v0.8.1"}, } // docker run --name gomod --rm -it golang:1.15 bash @@ -31,19 +31,19 @@ var ( // go get github.com/BurntSushi/toml // go list -m all | awk 'NR>1 {sub(/^v/, "", $2); printf("{\""$1"\", \""$2"\", },\n")}' GoModMany = []ftypes.Package{ - {Name: "github.com/BurntSushi/toml", Version: "0.3.1"}, - {Name: "github.com/cpuguy83/go-md2man/v2", Version: "2.0.0-20190314233015-f79a8a8ca69d"}, - {Name: "github.com/davecgh/go-spew", Version: "1.1.0"}, - {Name: "github.com/pmezard/go-difflib", Version: "1.0.0"}, - {Name: "github.com/russross/blackfriday/v2", Version: "2.0.1"}, - {Name: "github.com/shurcooL/sanitized_anchor_name", Version: "1.0.0"}, - {Name: "github.com/stretchr/objx", Version: "0.1.0"}, - {Name: "github.com/stretchr/testify", Version: "1.7.0"}, - {Name: "github.com/urfave/cli", Version: "1.22.5"}, - {Name: "golang.org/x/xerrors", Version: "0.0.0-20200804184101-5ec99f83aff1"}, - {Name: "gopkg.in/check.v1", Version: "0.0.0-20161208181325-20d25e280405"}, - {Name: "gopkg.in/yaml.v2", Version: "2.2.2"}, - {Name: "gopkg.in/yaml.v3", Version: "3.0.0-20200313102051-9f266ea9e77c"}, + {Name: "github.com/BurntSushi/toml", Version: "v0.3.1"}, + {Name: "github.com/cpuguy83/go-md2man/v2", Version: "v2.0.0-20190314233015-f79a8a8ca69d"}, + {Name: "github.com/davecgh/go-spew", Version: "v1.1.0"}, + {Name: "github.com/pmezard/go-difflib", Version: "v1.0.0"}, + {Name: "github.com/russross/blackfriday/v2", Version: "v2.0.1"}, + {Name: "github.com/shurcooL/sanitized_anchor_name", Version: "v1.0.0"}, + {Name: "github.com/stretchr/objx", Version: "v0.1.0"}, + {Name: "github.com/stretchr/testify", Version: "v1.7.0"}, + {Name: "github.com/urfave/cli", Version: "v1.22.5"}, + {Name: "golang.org/x/xerrors", Version: "v0.0.0-20200804184101-5ec99f83aff1"}, + {Name: "gopkg.in/check.v1", Version: "v0.0.0-20161208181325-20d25e280405"}, + {Name: "gopkg.in/yaml.v2", Version: "v2.2.2"}, + {Name: "gopkg.in/yaml.v3", Version: "v3.0.0-20200313102051-9f266ea9e77c"}, } // docker run --name gomod --rm -it golang:1.15 bash @@ -54,341 +54,341 @@ var ( // go get github.com/aquasecurity/trivy // go list -m all | awk 'NR>1 {sub(/^v/, "", $2); printf("{\""$1"\", \""$2"\", },\n")}' GoModTrivy = []ftypes.Package{ - {Name: "cloud.google.com/go", Version: "0.65.0"}, - {Name: "cloud.google.com/go/bigquery", Version: "1.8.0"}, - {Name: "cloud.google.com/go/datastore", Version: "1.1.0"}, - {Name: "cloud.google.com/go/pubsub", Version: "1.3.1"}, - {Name: "cloud.google.com/go/storage", Version: "1.10.0"}, - {Name: "dmitri.shuralyov.com/gpu/mtl", Version: "0.0.0-20190408044501-666a987793e9"}, - {Name: "github.com/Azure/azure-sdk-for-go", Version: "38.0.0+incompatible"}, - {Name: "github.com/Azure/go-ansiterm", Version: "0.0.0-20170929234023-d6e3b3328b78"}, - {Name: "github.com/Azure/go-autorest/autorest", Version: "0.9.3"}, - {Name: "github.com/Azure/go-autorest/autorest/adal", Version: "0.8.1"}, - {Name: "github.com/Azure/go-autorest/autorest/date", Version: "0.2.0"}, - {Name: "github.com/Azure/go-autorest/autorest/mocks", Version: "0.3.0"}, - {Name: "github.com/Azure/go-autorest/autorest/to", Version: "0.3.0"}, - {Name: "github.com/Azure/go-autorest/autorest/validation", Version: "0.1.0"}, - {Name: "github.com/Azure/go-autorest/logger", Version: "0.1.0"}, - {Name: "github.com/Azure/go-autorest/tracing", Version: "0.5.0"}, - {Name: "github.com/BurntSushi/toml", Version: "0.3.1"}, - {Name: "github.com/BurntSushi/xgb", Version: "0.0.0-20160522181843-27f122750802"}, - {Name: "github.com/GoogleCloudPlatform/docker-credential-gcr", Version: "1.5.0"}, - {Name: "github.com/GoogleCloudPlatform/k8s-cloud-provider", Version: "0.0.0-20190822182118-27a4ced34534"}, - {Name: "github.com/Microsoft/go-winio", Version: "0.4.15-0.20190919025122-fc70bd9a86b5"}, - {Name: "github.com/Microsoft/hcsshim", Version: "0.8.6"}, - {Name: "github.com/NYTimes/gziphandler", Version: "0.0.0-20170623195520-56545f4a5d46"}, - {Name: "github.com/OneOfOne/xxhash", Version: "1.2.7"}, - {Name: "github.com/PuerkitoBio/purell", Version: "1.1.1"}, - {Name: "github.com/PuerkitoBio/urlesc", Version: "0.0.0-20170810143723-de5bf2ad4578"}, - {Name: "github.com/VividCortex/ewma", Version: "1.1.1"}, - {Name: "github.com/alcortesm/tgz", Version: "0.0.0-20161220082320-9c5fe88206d7"}, - {Name: "github.com/alecthomas/template", Version: "0.0.0-20160405071501-a0175ee3bccc"}, - {Name: "github.com/alecthomas/units", Version: "0.0.0-20151022065526-2efee857e7cf"}, - {Name: "github.com/alicebob/gopher-json", Version: "0.0.0-20200520072559-a9ecdc9d1d3a"}, - {Name: "github.com/alicebob/miniredis/v2", Version: "2.14.1"}, - {Name: "github.com/anmitsu/go-shlex", Version: "0.0.0-20161002113705-648efa622239"}, - {Name: "github.com/aquasecurity/bolt-fixtures", Version: "0.0.0-20200903104109-d34e7f983986"}, - {Name: "github.com/aquasecurity/fanal", Version: "0.0.0-20210119051230-28c249da7cfd"}, - {Name: "github.com/aquasecurity/go-dep-parser", Version: "0.0.0-20201028043324-889d4a92b8e0"}, - {Name: "github.com/aquasecurity/go-gem-version", Version: "0.0.0-20201115065557-8eed6fe000ce"}, - {Name: "github.com/aquasecurity/go-npm-version", Version: "0.0.0-20201110091526-0b796d180798"}, - {Name: "github.com/aquasecurity/go-pep440-version", Version: "0.0.0-20210121094942-22b2f8951d46"}, - {Name: "github.com/aquasecurity/go-version", Version: "0.0.0-20210121072130-637058cfe492"}, - {Name: "github.com/aquasecurity/testdocker", Version: "0.0.0-20210106133225-0b17fe083674"}, - {Name: "github.com/aquasecurity/trivy", Version: "0.16.0"}, - {Name: "github.com/aquasecurity/trivy-db", Version: "0.0.0-20210105160501-c5bf4e153277"}, - {Name: "github.com/aquasecurity/vuln-list-update", Version: "0.0.0-20191016075347-3d158c2bf9a2"}, - {Name: "github.com/araddon/dateparse", Version: "0.0.0-20190426192744-0d74ffceef83"}, - {Name: "github.com/armon/consul-api", Version: "0.0.0-20180202201655-eb2c6b5be1b6"}, - {Name: "github.com/armon/go-socks5", Version: "0.0.0-20160902184237-e75332964ef5"}, - {Name: "github.com/aws/aws-sdk-go", Version: "1.27.1"}, - {Name: "github.com/beorn7/perks", Version: "1.0.0"}, - {Name: "github.com/bgentry/speakeasy", Version: "0.1.0"}, - {Name: "github.com/blang/semver", Version: "3.5.0+incompatible"}, - {Name: "github.com/briandowns/spinner", Version: "1.12.0"}, - {Name: "github.com/caarlos0/env/v6", Version: "6.0.0"}, - {Name: "github.com/cenkalti/backoff", Version: "2.2.1+incompatible"}, - {Name: "github.com/census-instrumentation/opencensus-proto", Version: "0.2.1"}, - {Name: "github.com/cespare/xxhash/v2", Version: "2.1.1"}, - {Name: "github.com/cheggaaa/pb/v3", Version: "3.0.3"}, - {Name: "github.com/chzyer/logex", Version: "1.1.10"}, - {Name: "github.com/chzyer/readline", Version: "0.0.0-20180603132655-2972be24d48e"}, - {Name: "github.com/chzyer/test", Version: "0.0.0-20180213035817-a1ea475d72b1"}, - {Name: "github.com/client9/misspell", Version: "0.3.4"}, - {Name: "github.com/cncf/udpa/go", Version: "0.0.0-20191209042840-269d4d468f6f"}, - {Name: "github.com/cockroachdb/datadriven", Version: "0.0.0-20190809214429-80d97fb3cbaa"}, - {Name: "github.com/containerd/containerd", Version: "1.3.3"}, - {Name: "github.com/containerd/continuity", Version: "0.0.0-20190426062206-aaeac12a7ffc"}, - {Name: "github.com/coreos/etcd", Version: "3.3.10+incompatible"}, - {Name: "github.com/coreos/go-etcd", Version: "2.0.0+incompatible"}, - {Name: "github.com/coreos/go-oidc", Version: "2.1.0+incompatible"}, - {Name: "github.com/coreos/go-semver", Version: "0.3.0"}, - {Name: "github.com/coreos/go-systemd", Version: "0.0.0-20190321100706-95778dfbb74e"}, - {Name: "github.com/coreos/pkg", Version: "0.0.0-20180108230652-97fdf19511ea"}, - {Name: "github.com/cpuguy83/go-md2man", Version: "1.0.10"}, - {Name: "github.com/cpuguy83/go-md2man/v2", Version: "2.0.0"}, - {Name: "github.com/creack/pty", Version: "1.1.9"}, - {Name: "github.com/davecgh/go-spew", Version: "1.1.1"}, - {Name: "github.com/deckarep/golang-set", Version: "1.7.1"}, - {Name: "github.com/dgrijalva/jwt-go", Version: "3.2.0+incompatible"}, - {Name: "github.com/dgryski/go-rendezvous", Version: "0.0.0-20200823014737-9f7001d12a5f"}, - {Name: "github.com/dnaeon/go-vcr", Version: "1.0.1"}, - {Name: "github.com/docker/cli", Version: "0.0.0-20191017083524-a8ff7f821017"}, - {Name: "github.com/docker/distribution", Version: "2.7.1+incompatible"}, - {Name: "github.com/docker/docker", Version: "1.4.2-0.20190924003213-a8608b5b67c7"}, - {Name: "github.com/docker/docker-credential-helpers", Version: "0.6.3"}, - {Name: "github.com/docker/go-connections", Version: "0.4.0"}, - {Name: "github.com/docker/go-units", Version: "0.4.0"}, - {Name: "github.com/docker/spdystream", Version: "0.0.0-20160310174837-449fdfce4d96"}, - {Name: "github.com/dustin/go-humanize", Version: "1.0.0"}, - {Name: "github.com/elazarl/goproxy", Version: "0.0.0-20200809112317-0581fc3aee2d"}, - {Name: "github.com/elazarl/goproxy/ext", Version: "0.0.0-20200809112317-0581fc3aee2d"}, - {Name: "github.com/emicklei/go-restful", Version: "2.9.5+incompatible"}, - {Name: "github.com/emirpasic/gods", Version: "1.12.0"}, - {Name: "github.com/envoyproxy/go-control-plane", Version: "0.9.4"}, - {Name: "github.com/envoyproxy/protoc-gen-validate", Version: "0.1.0"}, - {Name: "github.com/evanphx/json-patch", Version: "4.2.0+incompatible"}, - {Name: "github.com/fatih/color", Version: "1.10.0"}, - {Name: "github.com/flynn/go-shlex", Version: "0.0.0-20150515145356-3f9db97f8568"}, - {Name: "github.com/fsnotify/fsnotify", Version: "1.4.9"}, - {Name: "github.com/ghodss/yaml", Version: "1.0.0"}, - {Name: "github.com/gin-contrib/sse", Version: "0.1.0"}, - {Name: "github.com/gin-gonic/gin", Version: "1.5.0"}, - {Name: "github.com/gliderlabs/ssh", Version: "0.2.2"}, - {Name: "github.com/go-git/gcfg", Version: "1.5.0"}, - {Name: "github.com/go-git/go-billy/v5", Version: "5.0.0"}, - {Name: "github.com/go-git/go-git-fixtures/v4", Version: "4.0.1"}, - {Name: "github.com/go-git/go-git/v5", Version: "5.0.0"}, - {Name: "github.com/go-gl/glfw", Version: "0.0.0-20190409004039-e6da0acd62b1"}, - {Name: "github.com/go-gl/glfw/v3.3/glfw", Version: "0.0.0-20200222043503-6f7a984d4dc4"}, - {Name: "github.com/go-kit/kit", Version: "0.8.0"}, - {Name: "github.com/go-logfmt/logfmt", Version: "0.3.0"}, - {Name: "github.com/go-logr/logr", Version: "0.1.0"}, - {Name: "github.com/go-openapi/jsonpointer", Version: "0.19.3"}, - {Name: "github.com/go-openapi/jsonreference", Version: "0.19.3"}, - {Name: "github.com/go-openapi/spec", Version: "0.19.3"}, - {Name: "github.com/go-openapi/swag", Version: "0.19.5"}, - {Name: "github.com/go-playground/locales", Version: "0.13.0"}, - {Name: "github.com/go-playground/universal-translator", Version: "0.17.0"}, - {Name: "github.com/go-redis/redis", Version: "6.15.7+incompatible"}, - {Name: "github.com/go-redis/redis/v8", Version: "8.4.0"}, - {Name: "github.com/go-restruct/restruct", Version: "0.0.0-20191227155143-5734170a48a1"}, - {Name: "github.com/go-sql-driver/mysql", Version: "1.5.0"}, - {Name: "github.com/go-stack/stack", Version: "1.8.0"}, - {Name: "github.com/gobwas/glob", Version: "0.2.3"}, - {Name: "github.com/goccy/go-yaml", Version: "1.8.2"}, - {Name: "github.com/gogo/protobuf", Version: "1.3.1"}, - {Name: "github.com/golang/glog", Version: "0.0.0-20160126235308-23def4e6c14b"}, - {Name: "github.com/golang/groupcache", Version: "0.0.0-20200121045136-8c9f03a8e57e"}, - {Name: "github.com/golang/mock", Version: "1.4.4"}, - {Name: "github.com/golang/protobuf", Version: "1.4.2"}, - {Name: "github.com/google/btree", Version: "1.0.0"}, - {Name: "github.com/google/go-cmp", Version: "0.5.3"}, - {Name: "github.com/google/go-containerregistry", Version: "0.0.0-20200331213917-3d03ed9b1ca2"}, - {Name: "github.com/google/go-github/v28", Version: "28.1.1"}, - {Name: "github.com/google/go-querystring", Version: "1.0.0"}, - {Name: "github.com/google/gofuzz", Version: "1.0.0"}, - {Name: "github.com/google/martian", Version: "2.1.0+incompatible"}, - {Name: "github.com/google/martian/v3", Version: "3.0.0"}, - {Name: "github.com/google/pprof", Version: "0.0.0-20200708004538-1a94d8640e99"}, - {Name: "github.com/google/renameio", Version: "0.1.0"}, - {Name: "github.com/google/subcommands", Version: "1.0.1"}, - {Name: "github.com/google/uuid", Version: "1.1.1"}, - {Name: "github.com/google/wire", Version: "0.3.0"}, - {Name: "github.com/googleapis/gax-go/v2", Version: "2.0.5"}, - {Name: "github.com/googleapis/gnostic", Version: "0.2.2"}, - {Name: "github.com/gophercloud/gophercloud", Version: "0.1.0"}, - {Name: "github.com/gopherjs/gopherjs", Version: "0.0.0-20200217142428-fce0ec30dd00"}, - {Name: "github.com/gorilla/context", Version: "1.1.1"}, - {Name: "github.com/gorilla/mux", Version: "1.7.4"}, - {Name: "github.com/gorilla/websocket", Version: "1.4.0"}, - {Name: "github.com/gregjones/httpcache", Version: "0.0.0-20180305231024-9cad4c3443a7"}, - {Name: "github.com/grpc-ecosystem/go-grpc-middleware", Version: "1.0.1-0.20190118093823-f849b5445de4"}, - {Name: "github.com/grpc-ecosystem/go-grpc-prometheus", Version: "1.2.0"}, - {Name: "github.com/grpc-ecosystem/grpc-gateway", Version: "1.9.5"}, - {Name: "github.com/hashicorp/errwrap", Version: "1.0.0"}, - {Name: "github.com/hashicorp/go-multierror", Version: "1.1.0"}, - {Name: "github.com/hashicorp/go-version", Version: "1.2.1"}, - {Name: "github.com/hashicorp/golang-lru", Version: "0.5.3"}, - {Name: "github.com/hashicorp/hcl", Version: "1.0.0"}, - {Name: "github.com/hpcloud/tail", Version: "1.0.0"}, - {Name: "github.com/ianlancetaylor/demangle", Version: "0.0.0-20181102032728-5e5cf60278f6"}, - {Name: "github.com/imdario/mergo", Version: "0.3.5"}, - {Name: "github.com/inconshreveable/mousetrap", Version: "1.0.0"}, - {Name: "github.com/jbenet/go-context", Version: "0.0.0-20150711004518-d14ea06fba99"}, - {Name: "github.com/jessevdk/go-flags", Version: "1.4.0"}, - {Name: "github.com/jmespath/go-jmespath", Version: "0.0.0-20180206201540-c2b33e8439af"}, - {Name: "github.com/joefitzgerald/rainbow-reporter", Version: "0.1.0"}, - {Name: "github.com/jonboulle/clockwork", Version: "0.1.0"}, - {Name: "github.com/json-iterator/go", Version: "1.1.8"}, - {Name: "github.com/jstemmer/go-junit-report", Version: "0.9.1"}, - {Name: "github.com/jtolds/gls", Version: "4.20.0+incompatible"}, - {Name: "github.com/julienschmidt/httprouter", Version: "1.2.0"}, - {Name: "github.com/kevinburke/ssh_config", Version: "0.0.0-20190725054713-01f96b0aa0cd"}, - {Name: "github.com/kisielk/errcheck", Version: "1.2.0"}, - {Name: "github.com/kisielk/gotool", Version: "1.0.0"}, - {Name: "github.com/knqyf263/go-apk-version", Version: "0.0.0-20200609155635-041fdbb8563f"}, - {Name: "github.com/knqyf263/go-deb-version", Version: "0.0.0-20190517075300-09fca494f03d"}, - {Name: "github.com/knqyf263/go-rpm-version", Version: "0.0.0-20170716094938-74609b86c936"}, - {Name: "github.com/knqyf263/go-rpmdb", Version: "0.0.0-20201215100354-a9e3110d8ee1"}, - {Name: "github.com/knqyf263/nested", Version: "0.0.1"}, - {Name: "github.com/konsorten/go-windows-terminal-sequences", Version: "1.0.2"}, - {Name: "github.com/kr/logfmt", Version: "0.0.0-20140226030751-b84e30acd515"}, - {Name: "github.com/kr/pretty", Version: "0.1.0"}, - {Name: "github.com/kr/pty", Version: "1.1.5"}, - {Name: "github.com/kr/text", Version: "0.2.0"}, - {Name: "github.com/kylelemons/godebug", Version: "1.1.0"}, - {Name: "github.com/leodido/go-urn", Version: "1.2.0"}, - {Name: "github.com/magiconair/properties", Version: "1.8.0"}, - {Name: "github.com/mailru/easyjson", Version: "0.7.0"}, - {Name: "github.com/mattn/go-colorable", Version: "0.1.8"}, - {Name: "github.com/mattn/go-isatty", Version: "0.0.12"}, - {Name: "github.com/mattn/go-jsonpointer", Version: "0.0.0-20180225143300-37667080efed"}, - {Name: "github.com/mattn/go-runewidth", Version: "0.0.9"}, - {Name: "github.com/matttproud/golang_protobuf_extensions", Version: "1.0.1"}, - {Name: "github.com/maxbrunsfeld/counterfeiter/v6", Version: "6.2.2"}, - {Name: "github.com/mitchellh/go-homedir", Version: "1.1.0"}, - {Name: "github.com/mitchellh/mapstructure", Version: "1.1.2"}, - {Name: "github.com/modern-go/concurrent", Version: "0.0.0-20180306012644-bacd9c7ef1dd"}, - {Name: "github.com/modern-go/reflect2", Version: "1.0.1"}, - {Name: "github.com/morikuni/aec", Version: "1.0.0"}, - {Name: "github.com/munnerz/goautoneg", Version: "0.0.0-20191010083416-a7dc8b61c822"}, - {Name: "github.com/mwitkow/go-conntrack", Version: "0.0.0-20161129095857-cc309e4a2223"}, - {Name: "github.com/mxk/go-flowrate", Version: "0.0.0-20140419014527-cca7078d478f"}, - {Name: "github.com/niemeyer/pretty", Version: "0.0.0-20200227124842-a10e7caefd8e"}, - {Name: "github.com/nxadm/tail", Version: "1.4.4"}, - {Name: "github.com/olekukonko/tablewriter", Version: "0.0.2-0.20190607075207-195002e6e56a"}, - {Name: "github.com/onsi/ginkgo", Version: "1.14.2"}, - {Name: "github.com/onsi/gomega", Version: "1.10.3"}, - {Name: "github.com/open-policy-agent/opa", Version: "0.21.1"}, - {Name: "github.com/opencontainers/go-digest", Version: "1.0.0-rc1"}, - {Name: "github.com/opencontainers/image-spec", Version: "1.0.2-0.20190823105129-775207bd45b6"}, - {Name: "github.com/opencontainers/runc", Version: "0.1.1"}, - {Name: "github.com/parnurzeal/gorequest", Version: "0.2.16"}, - {Name: "github.com/pelletier/go-toml", Version: "1.2.0"}, - {Name: "github.com/peterbourgon/diskv", Version: "2.0.1+incompatible"}, - {Name: "github.com/peterh/liner", Version: "0.0.0-20170211195444-bf27d3ba8e1d"}, - {Name: "github.com/pkg/errors", Version: "0.9.1"}, - {Name: "github.com/pmezard/go-difflib", Version: "1.0.0"}, - {Name: "github.com/pquerna/cachecontrol", Version: "0.0.0-20171018203845-0dec1b30a021"}, - {Name: "github.com/prometheus/client_golang", Version: "1.0.0"}, - {Name: "github.com/prometheus/client_model", Version: "0.0.0-20190812154241-14fe0d1b01d4"}, - {Name: "github.com/prometheus/common", Version: "0.4.1"}, - {Name: "github.com/prometheus/procfs", Version: "0.0.2"}, - {Name: "github.com/rcrowley/go-metrics", Version: "0.0.0-20181016184325-3113b8401b8a"}, - {Name: "github.com/remyoudompheng/bigfft", Version: "0.0.0-20170806203942-52369c62f446"}, - {Name: "github.com/rogpeppe/fastuuid", Version: "0.0.0-20150106093220-6724a57986af"}, - {Name: "github.com/rogpeppe/go-charset", Version: "0.0.0-20180617210344-2471d30d28b4"}, - {Name: "github.com/rogpeppe/go-internal", Version: "1.3.0"}, - {Name: "github.com/rubiojr/go-vhd", Version: "0.0.0-20160810183302-0bfd3b39853c"}, - {Name: "github.com/russross/blackfriday", Version: "1.5.2"}, - {Name: "github.com/russross/blackfriday/v2", Version: "2.0.1"}, - {Name: "github.com/saracen/walker", Version: "0.0.0-20191201085201-324a081bae7e"}, - {Name: "github.com/satori/go.uuid", Version: "1.2.0"}, - {Name: "github.com/sclevine/spec", Version: "1.2.0"}, - {Name: "github.com/sergi/go-diff", Version: "1.1.0"}, - {Name: "github.com/shurcooL/sanitized_anchor_name", Version: "1.0.0"}, - {Name: "github.com/simplereach/timeutils", Version: "1.2.0"}, - {Name: "github.com/sirupsen/logrus", Version: "1.5.0"}, - {Name: "github.com/smartystreets/assertions", Version: "1.2.0"}, - {Name: "github.com/smartystreets/goconvey", Version: "1.6.4"}, - {Name: "github.com/soheilhy/cmux", Version: "0.1.4"}, - {Name: "github.com/sosedoff/gitkit", Version: "0.2.0"}, - {Name: "github.com/spf13/afero", Version: "1.2.2"}, - {Name: "github.com/spf13/cast", Version: "1.3.0"}, - {Name: "github.com/spf13/cobra", Version: "0.0.5"}, - {Name: "github.com/spf13/jwalterweatherman", Version: "1.0.0"}, - {Name: "github.com/spf13/pflag", Version: "1.0.5"}, - {Name: "github.com/spf13/viper", Version: "1.3.2"}, - {Name: "github.com/stretchr/objx", Version: "0.3.0"}, - {Name: "github.com/stretchr/testify", Version: "1.6.1"}, - {Name: "github.com/testcontainers/testcontainers-go", Version: "0.3.1"}, - {Name: "github.com/tmc/grpc-websocket-proxy", Version: "0.0.0-20170815181823-89b8d40f7ca8"}, - {Name: "github.com/twitchtv/twirp", Version: "5.10.1+incompatible"}, - {Name: "github.com/ugorji/go", Version: "1.1.7"}, - {Name: "github.com/ugorji/go/codec", Version: "1.1.7"}, - {Name: "github.com/urfave/cli", Version: "1.22.5"}, - {Name: "github.com/urfave/cli/v2", Version: "2.3.0"}, - {Name: "github.com/vdemeester/k8s-pkg-credentialprovider", Version: "1.17.4"}, - {Name: "github.com/vmware/govmomi", Version: "0.20.3"}, - {Name: "github.com/xanzy/ssh-agent", Version: "0.2.1"}, - {Name: "github.com/xiang90/probing", Version: "0.0.0-20190116061207-43a291ad63a2"}, - {Name: "github.com/xordataexchange/crypt", Version: "0.0.3-0.20170626215501-b2862e3d0a77"}, - {Name: "github.com/yashtewari/glob-intersection", Version: "0.0.0-20180916065949-5c77d914dd0b"}, - {Name: "github.com/yuin/goldmark", Version: "1.1.32"}, - {Name: "github.com/yuin/gopher-lua", Version: "0.0.0-20191220021717-ab39c6098bdb"}, - {Name: "go.etcd.io/bbolt", Version: "1.3.5"}, - {Name: "go.etcd.io/etcd", Version: "0.0.0-20191023171146-3cf2f69b5738"}, - {Name: "go.opencensus.io", Version: "0.22.4"}, - {Name: "go.opentelemetry.io/otel", Version: "0.14.0"}, - {Name: "go.uber.org/atomic", Version: "1.5.1"}, - {Name: "go.uber.org/multierr", Version: "1.4.0"}, - {Name: "go.uber.org/tools", Version: "0.0.0-20190618225709-2cfd321de3ee"}, - {Name: "go.uber.org/zap", Version: "1.13.0"}, - {Name: "golang.org/x/crypto", Version: "0.0.0-20201002170205-7f63de1d35b0"}, - {Name: "golang.org/x/exp", Version: "0.0.0-20200224162631-6cc2880d07d6"}, - {Name: "golang.org/x/image", Version: "0.0.0-20190802002840-cff245a6509b"}, - {Name: "golang.org/x/lint", Version: "0.0.0-20200302205851-738671d3881b"}, - {Name: "golang.org/x/mobile", Version: "0.0.0-20190719004257-d2bd2a29d028"}, - {Name: "golang.org/x/mod", Version: "0.3.0"}, - {Name: "golang.org/x/net", Version: "0.0.0-20201006153459-a7d1128ccaa0"}, - {Name: "golang.org/x/oauth2", Version: "0.0.0-20201208152858-08078c50e5b5"}, - {Name: "golang.org/x/sync", Version: "0.0.0-20200625203802-6e8e738ad208"}, - {Name: "golang.org/x/sys", Version: "0.0.0-20201006155630-ac719f4daadf"}, - {Name: "golang.org/x/text", Version: "0.3.3"}, - {Name: "golang.org/x/time", Version: "0.0.0-20191024005414-555d28b269f0"}, - {Name: "golang.org/x/tools", Version: "0.0.0-20200825202427-b303f430e36d"}, - {Name: "golang.org/x/xerrors", Version: "0.0.0-20200804184101-5ec99f83aff1"}, - {Name: "gonum.org/v1/gonum", Version: "0.0.0-20190331200053-3d26580ed485"}, - {Name: "gonum.org/v1/netlib", Version: "0.0.0-20190331212654-76723241ea4e"}, - {Name: "google.golang.org/api", Version: "0.30.0"}, - {Name: "google.golang.org/appengine", Version: "1.6.6"}, - {Name: "google.golang.org/genproto", Version: "0.0.0-20200825200019-8632dd797987"}, - {Name: "google.golang.org/grpc", Version: "1.31.0"}, - {Name: "google.golang.org/protobuf", Version: "1.25.0"}, - {Name: "gopkg.in/alecthomas/kingpin.v2", Version: "2.2.6"}, - {Name: "gopkg.in/check.v1", Version: "1.0.0-20200902074654-038fdea0a05b"}, - {Name: "gopkg.in/cheggaaa/pb.v1", Version: "1.0.28"}, - {Name: "gopkg.in/errgo.v2", Version: "2.1.0"}, - {Name: "gopkg.in/fsnotify.v1", Version: "1.4.7"}, - {Name: "gopkg.in/gcfg.v1", Version: "1.2.0"}, - {Name: "gopkg.in/go-playground/assert.v1", Version: "1.2.1"}, - {Name: "gopkg.in/go-playground/validator.v9", Version: "9.31.0"}, - {Name: "gopkg.in/inf.v0", Version: "0.9.1"}, - {Name: "gopkg.in/mgo.v2", Version: "2.0.0-20180705113604-9856a29383ce"}, - {Name: "gopkg.in/natefinch/lumberjack.v2", Version: "2.0.0"}, - {Name: "gopkg.in/resty.v1", Version: "1.12.0"}, - {Name: "gopkg.in/square/go-jose.v2", Version: "2.2.2"}, - {Name: "gopkg.in/tomb.v1", Version: "1.0.0-20141024135613-dd632973f1e7"}, - {Name: "gopkg.in/warnings.v0", Version: "0.1.2"}, - {Name: "gopkg.in/yaml.v2", Version: "2.4.0"}, - {Name: "gopkg.in/yaml.v3", Version: "3.0.0-20200615113413-eeeca48fe776"}, - {Name: "gotest.tools", Version: "2.2.0+incompatible"}, - {Name: "honnef.co/go/tools", Version: "0.0.1-2020.1.4"}, - {Name: "k8s.io/api", Version: "0.17.4"}, - {Name: "k8s.io/apimachinery", Version: "0.17.4"}, - {Name: "k8s.io/apiserver", Version: "0.17.4"}, - {Name: "k8s.io/client-go", Version: "0.17.4"}, - {Name: "k8s.io/cloud-provider", Version: "0.17.4"}, - {Name: "k8s.io/code-generator", Version: "0.17.2"}, - {Name: "k8s.io/component-base", Version: "0.17.4"}, - {Name: "k8s.io/csi-translation-lib", Version: "0.17.4"}, - {Name: "k8s.io/gengo", Version: "0.0.0-20190822140433-26a664648505"}, - {Name: "k8s.io/klog", Version: "1.0.0"}, - {Name: "k8s.io/klog/v2", Version: "2.0.0"}, - {Name: "k8s.io/kube-openapi", Version: "0.0.0-20191107075043-30be4d16710a"}, - {Name: "k8s.io/legacy-cloud-providers", Version: "0.17.4"}, - {Name: "k8s.io/utils", Version: "0.0.0-20201110183641-67b214c5f920"}, - {Name: "modernc.org/cc", Version: "1.0.0"}, - {Name: "modernc.org/golex", Version: "1.0.0"}, - {Name: "modernc.org/mathutil", Version: "1.0.0"}, - {Name: "modernc.org/strutil", Version: "1.0.0"}, - {Name: "modernc.org/xc", Version: "1.0.0"}, - {Name: "moul.io/http2curl", Version: "1.0.0"}, - {Name: "rsc.io/binaryregexp", Version: "0.2.0"}, - {Name: "rsc.io/quote/v3", Version: "3.1.0"}, - {Name: "rsc.io/sampler", Version: "1.3.0"}, - {Name: "sigs.k8s.io/structured-merge-diff", Version: "1.0.1-0.20191108220359-b1b620dd3f06"}, - {Name: "sigs.k8s.io/yaml", Version: "1.1.0"}, + {Name: "cloud.google.com/go", Version: "v0.65.0"}, + {Name: "cloud.google.com/go/bigquery", Version: "v1.8.0"}, + {Name: "cloud.google.com/go/datastore", Version: "v1.1.0"}, + {Name: "cloud.google.com/go/pubsub", Version: "v1.3.1"}, + {Name: "cloud.google.com/go/storage", Version: "v1.10.0"}, + {Name: "dmitri.shuralyov.com/gpu/mtl", Version: "v0.0.0-20190408044501-666a987793e9"}, + {Name: "github.com/Azure/azure-sdk-for-go", Version: "v38.0.0+incompatible"}, + {Name: "github.com/Azure/go-ansiterm", Version: "v0.0.0-20170929234023-d6e3b3328b78"}, + {Name: "github.com/Azure/go-autorest/autorest", Version: "v0.9.3"}, + {Name: "github.com/Azure/go-autorest/autorest/adal", Version: "v0.8.1"}, + {Name: "github.com/Azure/go-autorest/autorest/date", Version: "v0.2.0"}, + {Name: "github.com/Azure/go-autorest/autorest/mocks", Version: "v0.3.0"}, + {Name: "github.com/Azure/go-autorest/autorest/to", Version: "v0.3.0"}, + {Name: "github.com/Azure/go-autorest/autorest/validation", Version: "v0.1.0"}, + {Name: "github.com/Azure/go-autorest/logger", Version: "v0.1.0"}, + {Name: "github.com/Azure/go-autorest/tracing", Version: "v0.5.0"}, + {Name: "github.com/BurntSushi/toml", Version: "v0.3.1"}, + {Name: "github.com/BurntSushi/xgb", Version: "v0.0.0-20160522181843-27f122750802"}, + {Name: "github.com/GoogleCloudPlatform/docker-credential-gcr", Version: "v1.5.0"}, + {Name: "github.com/GoogleCloudPlatform/k8s-cloud-provider", Version: "v0.0.0-20190822182118-27a4ced34534"}, + {Name: "github.com/Microsoft/go-winio", Version: "v0.4.15-0.20190919025122-fc70bd9a86b5"}, + {Name: "github.com/Microsoft/hcsshim", Version: "v0.8.6"}, + {Name: "github.com/NYTimes/gziphandler", Version: "v0.0.0-20170623195520-56545f4a5d46"}, + {Name: "github.com/OneOfOne/xxhash", Version: "v1.2.7"}, + {Name: "github.com/PuerkitoBio/purell", Version: "v1.1.1"}, + {Name: "github.com/PuerkitoBio/urlesc", Version: "v0.0.0-20170810143723-de5bf2ad4578"}, + {Name: "github.com/VividCortex/ewma", Version: "v1.1.1"}, + {Name: "github.com/alcortesm/tgz", Version: "v0.0.0-20161220082320-9c5fe88206d7"}, + {Name: "github.com/alecthomas/template", Version: "v0.0.0-20160405071501-a0175ee3bccc"}, + {Name: "github.com/alecthomas/units", Version: "v0.0.0-20151022065526-2efee857e7cf"}, + {Name: "github.com/alicebob/gopher-json", Version: "v0.0.0-20200520072559-a9ecdc9d1d3a"}, + {Name: "github.com/alicebob/miniredis/v2", Version: "v2.14.1"}, + {Name: "github.com/anmitsu/go-shlex", Version: "v0.0.0-20161002113705-648efa622239"}, + {Name: "github.com/aquasecurity/bolt-fixtures", Version: "v0.0.0-20200903104109-d34e7f983986"}, + {Name: "github.com/aquasecurity/fanal", Version: "v0.0.0-20210119051230-28c249da7cfd"}, + {Name: "github.com/aquasecurity/go-dep-parser", Version: "v0.0.0-20201028043324-889d4a92b8e0"}, + {Name: "github.com/aquasecurity/go-gem-version", Version: "v0.0.0-20201115065557-8eed6fe000ce"}, + {Name: "github.com/aquasecurity/go-npm-version", Version: "v0.0.0-20201110091526-0b796d180798"}, + {Name: "github.com/aquasecurity/go-pep440-version", Version: "v0.0.0-20210121094942-22b2f8951d46"}, + {Name: "github.com/aquasecurity/go-version", Version: "v0.0.0-20210121072130-637058cfe492"}, + {Name: "github.com/aquasecurity/testdocker", Version: "v0.0.0-20210106133225-0b17fe083674"}, + {Name: "github.com/aquasecurity/trivy", Version: "v0.16.0"}, + {Name: "github.com/aquasecurity/trivy-db", Version: "v0.0.0-20210105160501-c5bf4e153277"}, + {Name: "github.com/aquasecurity/vuln-list-update", Version: "v0.0.0-20191016075347-3d158c2bf9a2"}, + {Name: "github.com/araddon/dateparse", Version: "v0.0.0-20190426192744-0d74ffceef83"}, + {Name: "github.com/armon/consul-api", Version: "v0.0.0-20180202201655-eb2c6b5be1b6"}, + {Name: "github.com/armon/go-socks5", Version: "v0.0.0-20160902184237-e75332964ef5"}, + {Name: "github.com/aws/aws-sdk-go", Version: "v1.27.1"}, + {Name: "github.com/beorn7/perks", Version: "v1.0.0"}, + {Name: "github.com/bgentry/speakeasy", Version: "v0.1.0"}, + {Name: "github.com/blang/semver", Version: "v3.5.0+incompatible"}, + {Name: "github.com/briandowns/spinner", Version: "v1.12.0"}, + {Name: "github.com/caarlos0/env/v6", Version: "v6.0.0"}, + {Name: "github.com/cenkalti/backoff", Version: "v2.2.1+incompatible"}, + {Name: "github.com/census-instrumentation/opencensus-proto", Version: "v0.2.1"}, + {Name: "github.com/cespare/xxhash/v2", Version: "v2.1.1"}, + {Name: "github.com/cheggaaa/pb/v3", Version: "v3.0.3"}, + {Name: "github.com/chzyer/logex", Version: "v1.1.10"}, + {Name: "github.com/chzyer/readline", Version: "v0.0.0-20180603132655-2972be24d48e"}, + {Name: "github.com/chzyer/test", Version: "v0.0.0-20180213035817-a1ea475d72b1"}, + {Name: "github.com/client9/misspell", Version: "v0.3.4"}, + {Name: "github.com/cncf/udpa/go", Version: "v0.0.0-20191209042840-269d4d468f6f"}, + {Name: "github.com/cockroachdb/datadriven", Version: "v0.0.0-20190809214429-80d97fb3cbaa"}, + {Name: "github.com/containerd/containerd", Version: "v1.3.3"}, + {Name: "github.com/containerd/continuity", Version: "v0.0.0-20190426062206-aaeac12a7ffc"}, + {Name: "github.com/coreos/etcd", Version: "v3.3.10+incompatible"}, + {Name: "github.com/coreos/go-etcd", Version: "v2.0.0+incompatible"}, + {Name: "github.com/coreos/go-oidc", Version: "v2.1.0+incompatible"}, + {Name: "github.com/coreos/go-semver", Version: "v0.3.0"}, + {Name: "github.com/coreos/go-systemd", Version: "v0.0.0-20190321100706-95778dfbb74e"}, + {Name: "github.com/coreos/pkg", Version: "v0.0.0-20180108230652-97fdf19511ea"}, + {Name: "github.com/cpuguy83/go-md2man", Version: "v1.0.10"}, + {Name: "github.com/cpuguy83/go-md2man/v2", Version: "v2.0.0"}, + {Name: "github.com/creack/pty", Version: "v1.1.9"}, + {Name: "github.com/davecgh/go-spew", Version: "v1.1.1"}, + {Name: "github.com/deckarep/golang-set", Version: "v1.7.1"}, + {Name: "github.com/dgrijalva/jwt-go", Version: "v3.2.0+incompatible"}, + {Name: "github.com/dgryski/go-rendezvous", Version: "v0.0.0-20200823014737-9f7001d12a5f"}, + {Name: "github.com/dnaeon/go-vcr", Version: "v1.0.1"}, + {Name: "github.com/docker/cli", Version: "v0.0.0-20191017083524-a8ff7f821017"}, + {Name: "github.com/docker/distribution", Version: "v2.7.1+incompatible"}, + {Name: "github.com/docker/docker", Version: "v1.4.2-0.20190924003213-a8608b5b67c7"}, + {Name: "github.com/docker/docker-credential-helpers", Version: "v0.6.3"}, + {Name: "github.com/docker/go-connections", Version: "v0.4.0"}, + {Name: "github.com/docker/go-units", Version: "v0.4.0"}, + {Name: "github.com/docker/spdystream", Version: "v0.0.0-20160310174837-449fdfce4d96"}, + {Name: "github.com/dustin/go-humanize", Version: "v1.0.0"}, + {Name: "github.com/elazarl/goproxy", Version: "v0.0.0-20200809112317-0581fc3aee2d"}, + {Name: "github.com/elazarl/goproxy/ext", Version: "v0.0.0-20200809112317-0581fc3aee2d"}, + {Name: "github.com/emicklei/go-restful", Version: "v2.9.5+incompatible"}, + {Name: "github.com/emirpasic/gods", Version: "v1.12.0"}, + {Name: "github.com/envoyproxy/go-control-plane", Version: "v0.9.4"}, + {Name: "github.com/envoyproxy/protoc-gen-validate", Version: "v0.1.0"}, + {Name: "github.com/evanphx/json-patch", Version: "v4.2.0+incompatible"}, + {Name: "github.com/fatih/color", Version: "v1.10.0"}, + {Name: "github.com/flynn/go-shlex", Version: "v0.0.0-20150515145356-3f9db97f8568"}, + {Name: "github.com/fsnotify/fsnotify", Version: "v1.4.9"}, + {Name: "github.com/ghodss/yaml", Version: "v1.0.0"}, + {Name: "github.com/gin-contrib/sse", Version: "v0.1.0"}, + {Name: "github.com/gin-gonic/gin", Version: "v1.5.0"}, + {Name: "github.com/gliderlabs/ssh", Version: "v0.2.2"}, + {Name: "github.com/go-git/gcfg", Version: "v1.5.0"}, + {Name: "github.com/go-git/go-billy/v5", Version: "v5.0.0"}, + {Name: "github.com/go-git/go-git-fixtures/v4", Version: "v4.0.1"}, + {Name: "github.com/go-git/go-git/v5", Version: "v5.0.0"}, + {Name: "github.com/go-gl/glfw", Version: "v0.0.0-20190409004039-e6da0acd62b1"}, + {Name: "github.com/go-gl/glfw/v3.3/glfw", Version: "v0.0.0-20200222043503-6f7a984d4dc4"}, + {Name: "github.com/go-kit/kit", Version: "v0.8.0"}, + {Name: "github.com/go-logfmt/logfmt", Version: "v0.3.0"}, + {Name: "github.com/go-logr/logr", Version: "v0.1.0"}, + {Name: "github.com/go-openapi/jsonpointer", Version: "v0.19.3"}, + {Name: "github.com/go-openapi/jsonreference", Version: "v0.19.3"}, + {Name: "github.com/go-openapi/spec", Version: "v0.19.3"}, + {Name: "github.com/go-openapi/swag", Version: "v0.19.5"}, + {Name: "github.com/go-playground/locales", Version: "v0.13.0"}, + {Name: "github.com/go-playground/universal-translator", Version: "v0.17.0"}, + {Name: "github.com/go-redis/redis", Version: "v6.15.7+incompatible"}, + {Name: "github.com/go-redis/redis/v8", Version: "v8.4.0"}, + {Name: "github.com/go-restruct/restruct", Version: "v0.0.0-20191227155143-5734170a48a1"}, + {Name: "github.com/go-sql-driver/mysql", Version: "v1.5.0"}, + {Name: "github.com/go-stack/stack", Version: "v1.8.0"}, + {Name: "github.com/gobwas/glob", Version: "v0.2.3"}, + {Name: "github.com/goccy/go-yaml", Version: "v1.8.2"}, + {Name: "github.com/gogo/protobuf", Version: "v1.3.1"}, + {Name: "github.com/golang/glog", Version: "v0.0.0-20160126235308-23def4e6c14b"}, + {Name: "github.com/golang/groupcache", Version: "v0.0.0-20200121045136-8c9f03a8e57e"}, + {Name: "github.com/golang/mock", Version: "v1.4.4"}, + {Name: "github.com/golang/protobuf", Version: "v1.4.2"}, + {Name: "github.com/google/btree", Version: "v1.0.0"}, + {Name: "github.com/google/go-cmp", Version: "v0.5.3"}, + {Name: "github.com/google/go-containerregistry", Version: "v0.0.0-20200331213917-3d03ed9b1ca2"}, + {Name: "github.com/google/go-github/v28", Version: "v28.1.1"}, + {Name: "github.com/google/go-querystring", Version: "v1.0.0"}, + {Name: "github.com/google/gofuzz", Version: "v1.0.0"}, + {Name: "github.com/google/martian", Version: "v2.1.0+incompatible"}, + {Name: "github.com/google/martian/v3", Version: "v3.0.0"}, + {Name: "github.com/google/pprof", Version: "v0.0.0-20200708004538-1a94d8640e99"}, + {Name: "github.com/google/renameio", Version: "v0.1.0"}, + {Name: "github.com/google/subcommands", Version: "v1.0.1"}, + {Name: "github.com/google/uuid", Version: "v1.1.1"}, + {Name: "github.com/google/wire", Version: "v0.3.0"}, + {Name: "github.com/googleapis/gax-go/v2", Version: "v2.0.5"}, + {Name: "github.com/googleapis/gnostic", Version: "v0.2.2"}, + {Name: "github.com/gophercloud/gophercloud", Version: "v0.1.0"}, + {Name: "github.com/gopherjs/gopherjs", Version: "v0.0.0-20200217142428-fce0ec30dd00"}, + {Name: "github.com/gorilla/context", Version: "v1.1.1"}, + {Name: "github.com/gorilla/mux", Version: "v1.7.4"}, + {Name: "github.com/gorilla/websocket", Version: "v1.4.0"}, + {Name: "github.com/gregjones/httpcache", Version: "v0.0.0-20180305231024-9cad4c3443a7"}, + {Name: "github.com/grpc-ecosystem/go-grpc-middleware", Version: "v1.0.1-0.20190118093823-f849b5445de4"}, + {Name: "github.com/grpc-ecosystem/go-grpc-prometheus", Version: "v1.2.0"}, + {Name: "github.com/grpc-ecosystem/grpc-gateway", Version: "v1.9.5"}, + {Name: "github.com/hashicorp/errwrap", Version: "v1.0.0"}, + {Name: "github.com/hashicorp/go-multierror", Version: "v1.1.0"}, + {Name: "github.com/hashicorp/go-version", Version: "v1.2.1"}, + {Name: "github.com/hashicorp/golang-lru", Version: "v0.5.3"}, + {Name: "github.com/hashicorp/hcl", Version: "v1.0.0"}, + {Name: "github.com/hpcloud/tail", Version: "v1.0.0"}, + {Name: "github.com/ianlancetaylor/demangle", Version: "v0.0.0-20181102032728-5e5cf60278f6"}, + {Name: "github.com/imdario/mergo", Version: "v0.3.5"}, + {Name: "github.com/inconshreveable/mousetrap", Version: "v1.0.0"}, + {Name: "github.com/jbenet/go-context", Version: "v0.0.0-20150711004518-d14ea06fba99"}, + {Name: "github.com/jessevdk/go-flags", Version: "v1.4.0"}, + {Name: "github.com/jmespath/go-jmespath", Version: "v0.0.0-20180206201540-c2b33e8439af"}, + {Name: "github.com/joefitzgerald/rainbow-reporter", Version: "v0.1.0"}, + {Name: "github.com/jonboulle/clockwork", Version: "v0.1.0"}, + {Name: "github.com/json-iterator/go", Version: "v1.1.8"}, + {Name: "github.com/jstemmer/go-junit-report", Version: "v0.9.1"}, + {Name: "github.com/jtolds/gls", Version: "v4.20.0+incompatible"}, + {Name: "github.com/julienschmidt/httprouter", Version: "v1.2.0"}, + {Name: "github.com/kevinburke/ssh_config", Version: "v0.0.0-20190725054713-01f96b0aa0cd"}, + {Name: "github.com/kisielk/errcheck", Version: "v1.2.0"}, + {Name: "github.com/kisielk/gotool", Version: "v1.0.0"}, + {Name: "github.com/knqyf263/go-apk-version", Version: "v0.0.0-20200609155635-041fdbb8563f"}, + {Name: "github.com/knqyf263/go-deb-version", Version: "v0.0.0-20190517075300-09fca494f03d"}, + {Name: "github.com/knqyf263/go-rpm-version", Version: "v0.0.0-20170716094938-74609b86c936"}, + {Name: "github.com/knqyf263/go-rpmdb", Version: "v0.0.0-20201215100354-a9e3110d8ee1"}, + {Name: "github.com/knqyf263/nested", Version: "v0.0.1"}, + {Name: "github.com/konsorten/go-windows-terminal-sequences", Version: "v1.0.2"}, + {Name: "github.com/kr/logfmt", Version: "v0.0.0-20140226030751-b84e30acd515"}, + {Name: "github.com/kr/pretty", Version: "v0.1.0"}, + {Name: "github.com/kr/pty", Version: "v1.1.5"}, + {Name: "github.com/kr/text", Version: "v0.2.0"}, + {Name: "github.com/kylelemons/godebug", Version: "v1.1.0"}, + {Name: "github.com/leodido/go-urn", Version: "v1.2.0"}, + {Name: "github.com/magiconair/properties", Version: "v1.8.0"}, + {Name: "github.com/mailru/easyjson", Version: "v0.7.0"}, + {Name: "github.com/mattn/go-colorable", Version: "v0.1.8"}, + {Name: "github.com/mattn/go-isatty", Version: "v0.0.12"}, + {Name: "github.com/mattn/go-jsonpointer", Version: "v0.0.0-20180225143300-37667080efed"}, + {Name: "github.com/mattn/go-runewidth", Version: "v0.0.9"}, + {Name: "github.com/matttproud/golang_protobuf_extensions", Version: "v1.0.1"}, + {Name: "github.com/maxbrunsfeld/counterfeiter/v6", Version: "v6.2.2"}, + {Name: "github.com/mitchellh/go-homedir", Version: "v1.1.0"}, + {Name: "github.com/mitchellh/mapstructure", Version: "v1.1.2"}, + {Name: "github.com/modern-go/concurrent", Version: "v0.0.0-20180306012644-bacd9c7ef1dd"}, + {Name: "github.com/modern-go/reflect2", Version: "v1.0.1"}, + {Name: "github.com/morikuni/aec", Version: "v1.0.0"}, + {Name: "github.com/munnerz/goautoneg", Version: "v0.0.0-20191010083416-a7dc8b61c822"}, + {Name: "github.com/mwitkow/go-conntrack", Version: "v0.0.0-20161129095857-cc309e4a2223"}, + {Name: "github.com/mxk/go-flowrate", Version: "v0.0.0-20140419014527-cca7078d478f"}, + {Name: "github.com/niemeyer/pretty", Version: "v0.0.0-20200227124842-a10e7caefd8e"}, + {Name: "github.com/nxadm/tail", Version: "v1.4.4"}, + {Name: "github.com/olekukonko/tablewriter", Version: "v0.0.2-0.20190607075207-195002e6e56a"}, + {Name: "github.com/onsi/ginkgo", Version: "v1.14.2"}, + {Name: "github.com/onsi/gomega", Version: "v1.10.3"}, + {Name: "github.com/open-policy-agent/opa", Version: "v0.21.1"}, + {Name: "github.com/opencontainers/go-digest", Version: "v1.0.0-rc1"}, + {Name: "github.com/opencontainers/image-spec", Version: "v1.0.2-0.20190823105129-775207bd45b6"}, + {Name: "github.com/opencontainers/runc", Version: "v0.1.1"}, + {Name: "github.com/parnurzeal/gorequest", Version: "v0.2.16"}, + {Name: "github.com/pelletier/go-toml", Version: "v1.2.0"}, + {Name: "github.com/peterbourgon/diskv", Version: "v2.0.1+incompatible"}, + {Name: "github.com/peterh/liner", Version: "v0.0.0-20170211195444-bf27d3ba8e1d"}, + {Name: "github.com/pkg/errors", Version: "v0.9.1"}, + {Name: "github.com/pmezard/go-difflib", Version: "v1.0.0"}, + {Name: "github.com/pquerna/cachecontrol", Version: "v0.0.0-20171018203845-0dec1b30a021"}, + {Name: "github.com/prometheus/client_golang", Version: "v1.0.0"}, + {Name: "github.com/prometheus/client_model", Version: "v0.0.0-20190812154241-14fe0d1b01d4"}, + {Name: "github.com/prometheus/common", Version: "v0.4.1"}, + {Name: "github.com/prometheus/procfs", Version: "v0.0.2"}, + {Name: "github.com/rcrowley/go-metrics", Version: "v0.0.0-20181016184325-3113b8401b8a"}, + {Name: "github.com/remyoudompheng/bigfft", Version: "v0.0.0-20170806203942-52369c62f446"}, + {Name: "github.com/rogpeppe/fastuuid", Version: "v0.0.0-20150106093220-6724a57986af"}, + {Name: "github.com/rogpeppe/go-charset", Version: "v0.0.0-20180617210344-2471d30d28b4"}, + {Name: "github.com/rogpeppe/go-internal", Version: "v1.3.0"}, + {Name: "github.com/rubiojr/go-vhd", Version: "v0.0.0-20160810183302-0bfd3b39853c"}, + {Name: "github.com/russross/blackfriday", Version: "v1.5.2"}, + {Name: "github.com/russross/blackfriday/v2", Version: "v2.0.1"}, + {Name: "github.com/saracen/walker", Version: "v0.0.0-20191201085201-324a081bae7e"}, + {Name: "github.com/satori/go.uuid", Version: "v1.2.0"}, + {Name: "github.com/sclevine/spec", Version: "v1.2.0"}, + {Name: "github.com/sergi/go-diff", Version: "v1.1.0"}, + {Name: "github.com/shurcooL/sanitized_anchor_name", Version: "v1.0.0"}, + {Name: "github.com/simplereach/timeutils", Version: "v1.2.0"}, + {Name: "github.com/sirupsen/logrus", Version: "v1.5.0"}, + {Name: "github.com/smartystreets/assertions", Version: "v1.2.0"}, + {Name: "github.com/smartystreets/goconvey", Version: "v1.6.4"}, + {Name: "github.com/soheilhy/cmux", Version: "v0.1.4"}, + {Name: "github.com/sosedoff/gitkit", Version: "v0.2.0"}, + {Name: "github.com/spf13/afero", Version: "v1.2.2"}, + {Name: "github.com/spf13/cast", Version: "v1.3.0"}, + {Name: "github.com/spf13/cobra", Version: "v0.0.5"}, + {Name: "github.com/spf13/jwalterweatherman", Version: "v1.0.0"}, + {Name: "github.com/spf13/pflag", Version: "v1.0.5"}, + {Name: "github.com/spf13/viper", Version: "v1.3.2"}, + {Name: "github.com/stretchr/objx", Version: "v0.3.0"}, + {Name: "github.com/stretchr/testify", Version: "v1.6.1"}, + {Name: "github.com/testcontainers/testcontainers-go", Version: "v0.3.1"}, + {Name: "github.com/tmc/grpc-websocket-proxy", Version: "v0.0.0-20170815181823-89b8d40f7ca8"}, + {Name: "github.com/twitchtv/twirp", Version: "v5.10.1+incompatible"}, + {Name: "github.com/ugorji/go", Version: "v1.1.7"}, + {Name: "github.com/ugorji/go/codec", Version: "v1.1.7"}, + {Name: "github.com/urfave/cli", Version: "v1.22.5"}, + {Name: "github.com/urfave/cli/v2", Version: "v2.3.0"}, + {Name: "github.com/vdemeester/k8s-pkg-credentialprovider", Version: "v1.17.4"}, + {Name: "github.com/vmware/govmomi", Version: "v0.20.3"}, + {Name: "github.com/xanzy/ssh-agent", Version: "v0.2.1"}, + {Name: "github.com/xiang90/probing", Version: "v0.0.0-20190116061207-43a291ad63a2"}, + {Name: "github.com/xordataexchange/crypt", Version: "v0.0.3-0.20170626215501-b2862e3d0a77"}, + {Name: "github.com/yashtewari/glob-intersection", Version: "v0.0.0-20180916065949-5c77d914dd0b"}, + {Name: "github.com/yuin/goldmark", Version: "v1.1.32"}, + {Name: "github.com/yuin/gopher-lua", Version: "v0.0.0-20191220021717-ab39c6098bdb"}, + {Name: "go.etcd.io/bbolt", Version: "v1.3.5"}, + {Name: "go.etcd.io/etcd", Version: "v0.0.0-20191023171146-3cf2f69b5738"}, + {Name: "go.opencensus.io", Version: "v0.22.4"}, + {Name: "go.opentelemetry.io/otel", Version: "v0.14.0"}, + {Name: "go.uber.org/atomic", Version: "v1.5.1"}, + {Name: "go.uber.org/multierr", Version: "v1.4.0"}, + {Name: "go.uber.org/tools", Version: "v0.0.0-20190618225709-2cfd321de3ee"}, + {Name: "go.uber.org/zap", Version: "v1.13.0"}, + {Name: "golang.org/x/crypto", Version: "v0.0.0-20201002170205-7f63de1d35b0"}, + {Name: "golang.org/x/exp", Version: "v0.0.0-20200224162631-6cc2880d07d6"}, + {Name: "golang.org/x/image", Version: "v0.0.0-20190802002840-cff245a6509b"}, + {Name: "golang.org/x/lint", Version: "v0.0.0-20200302205851-738671d3881b"}, + {Name: "golang.org/x/mobile", Version: "v0.0.0-20190719004257-d2bd2a29d028"}, + {Name: "golang.org/x/mod", Version: "v0.3.0"}, + {Name: "golang.org/x/net", Version: "v0.0.0-20201006153459-a7d1128ccaa0"}, + {Name: "golang.org/x/oauth2", Version: "v0.0.0-20201208152858-08078c50e5b5"}, + {Name: "golang.org/x/sync", Version: "v0.0.0-20200625203802-6e8e738ad208"}, + {Name: "golang.org/x/sys", Version: "v0.0.0-20201006155630-ac719f4daadf"}, + {Name: "golang.org/x/text", Version: "v0.3.3"}, + {Name: "golang.org/x/time", Version: "v0.0.0-20191024005414-555d28b269f0"}, + {Name: "golang.org/x/tools", Version: "v0.0.0-20200825202427-b303f430e36d"}, + {Name: "golang.org/x/xerrors", Version: "v0.0.0-20200804184101-5ec99f83aff1"}, + {Name: "gonum.org/v1/gonum", Version: "v0.0.0-20190331200053-3d26580ed485"}, + {Name: "gonum.org/v1/netlib", Version: "v0.0.0-20190331212654-76723241ea4e"}, + {Name: "google.golang.org/api", Version: "v0.30.0"}, + {Name: "google.golang.org/appengine", Version: "v1.6.6"}, + {Name: "google.golang.org/genproto", Version: "v0.0.0-20200825200019-8632dd797987"}, + {Name: "google.golang.org/grpc", Version: "v1.31.0"}, + {Name: "google.golang.org/protobuf", Version: "v1.25.0"}, + {Name: "gopkg.in/alecthomas/kingpin.v2", Version: "v2.2.6"}, + {Name: "gopkg.in/check.v1", Version: "v1.0.0-20200902074654-038fdea0a05b"}, + {Name: "gopkg.in/cheggaaa/pb.v1", Version: "v1.0.28"}, + {Name: "gopkg.in/errgo.v2", Version: "v2.1.0"}, + {Name: "gopkg.in/fsnotify.v1", Version: "v1.4.7"}, + {Name: "gopkg.in/gcfg.v1", Version: "v1.2.0"}, + {Name: "gopkg.in/go-playground/assert.v1", Version: "v1.2.1"}, + {Name: "gopkg.in/go-playground/validator.v9", Version: "v9.31.0"}, + {Name: "gopkg.in/inf.v0", Version: "v0.9.1"}, + {Name: "gopkg.in/mgo.v2", Version: "v2.0.0-20180705113604-9856a29383ce"}, + {Name: "gopkg.in/natefinch/lumberjack.v2", Version: "v2.0.0"}, + {Name: "gopkg.in/resty.v1", Version: "v1.12.0"}, + {Name: "gopkg.in/square/go-jose.v2", Version: "v2.2.2"}, + {Name: "gopkg.in/tomb.v1", Version: "v1.0.0-20141024135613-dd632973f1e7"}, + {Name: "gopkg.in/warnings.v0", Version: "v0.1.2"}, + {Name: "gopkg.in/yaml.v2", Version: "v2.4.0"}, + {Name: "gopkg.in/yaml.v3", Version: "v3.0.0-20200615113413-eeeca48fe776"}, + {Name: "gotest.tools", Version: "v2.2.0+incompatible"}, + {Name: "honnef.co/go/tools", Version: "v0.0.1-2020.1.4"}, + {Name: "k8s.io/api", Version: "v0.17.4"}, + {Name: "k8s.io/apimachinery", Version: "v0.17.4"}, + {Name: "k8s.io/apiserver", Version: "v0.17.4"}, + {Name: "k8s.io/client-go", Version: "v0.17.4"}, + {Name: "k8s.io/cloud-provider", Version: "v0.17.4"}, + {Name: "k8s.io/code-generator", Version: "v0.17.2"}, + {Name: "k8s.io/component-base", Version: "v0.17.4"}, + {Name: "k8s.io/csi-translation-lib", Version: "v0.17.4"}, + {Name: "k8s.io/gengo", Version: "v0.0.0-20190822140433-26a664648505"}, + {Name: "k8s.io/klog", Version: "v1.0.0"}, + {Name: "k8s.io/klog/v2", Version: "v2.0.0"}, + {Name: "k8s.io/kube-openapi", Version: "v0.0.0-20191107075043-30be4d16710a"}, + {Name: "k8s.io/legacy-cloud-providers", Version: "v0.17.4"}, + {Name: "k8s.io/utils", Version: "v0.0.0-20201110183641-67b214c5f920"}, + {Name: "modernc.org/cc", Version: "v1.0.0"}, + {Name: "modernc.org/golex", Version: "v1.0.0"}, + {Name: "modernc.org/mathutil", Version: "v1.0.0"}, + {Name: "modernc.org/strutil", Version: "v1.0.0"}, + {Name: "modernc.org/xc", Version: "v1.0.0"}, + {Name: "moul.io/http2curl", Version: "v1.0.0"}, + {Name: "rsc.io/binaryregexp", Version: "v0.2.0"}, + {Name: "rsc.io/quote/v3", Version: "v3.1.0"}, + {Name: "rsc.io/sampler", Version: "v1.3.0"}, + {Name: "sigs.k8s.io/structured-merge-diff", Version: "v1.0.1-0.20191108220359-b1b620dd3f06"}, + {Name: "sigs.k8s.io/yaml", Version: "v1.1.0"}, } ) diff --git a/pkg/fanal/analyzer/language/golang/binary/binary_test.go b/pkg/fanal/analyzer/language/golang/binary/binary_test.go index 70256113cfd3..041d43e1b45b 100644 --- a/pkg/fanal/analyzer/language/golang/binary/binary_test.go +++ b/pkg/fanal/analyzer/language/golang/binary/binary_test.go @@ -36,7 +36,7 @@ func Test_gobinaryLibraryAnalyzer_Analyze(t *testing.T) { }, { Name: "stdlib", - Version: "1.15.2", + Version: "v1.15.2", Relationship: types.RelationshipDirect, }, { diff --git a/pkg/fanal/analyzer/language/golang/mod/mod.go b/pkg/fanal/analyzer/language/golang/mod/mod.go index 398511fdc63c..52d7b32f3bee 100644 --- a/pkg/fanal/analyzer/language/golang/mod/mod.go +++ b/pkg/fanal/analyzer/language/golang/mod/mod.go @@ -148,7 +148,7 @@ func (a *gomodAnalyzer) fillAdditionalData(apps []types.Application) error { } // e.g. $GOPATH/pkg/mod/github.com/aquasecurity/go-dep-parser@v1.0.0 - modDir := filepath.Join(modPath, fmt.Sprintf("%s@v%s", normalizeModName(lib.Name), lib.Version)) + modDir := filepath.Join(modPath, fmt.Sprintf("%s@%s", normalizeModName(lib.Name), lib.Version)) // Collect licenses if licenseNames, err := findLicense(modDir, a.licenseClassifierConfidenceLevel); err != nil { diff --git a/pkg/fanal/analyzer/language/golang/mod/mod_test.go b/pkg/fanal/analyzer/language/golang/mod/mod_test.go index 5cf006430aca..3963bcebbad9 100644 --- a/pkg/fanal/analyzer/language/golang/mod/mod_test.go +++ b/pkg/fanal/analyzer/language/golang/mod/mod_test.go @@ -46,7 +46,7 @@ func Test_gomodAnalyzer_Analyze(t *testing.T) { { ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20220406074731-71021a481237", Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20220406074731-71021a481237", + Version: "v0.0.0-20220406074731-71021a481237", Relationship: types.RelationshipDirect, Licenses: []string{"MIT"}, ExternalReferences: []types.ExternalRef{ @@ -62,7 +62,7 @@ func Test_gomodAnalyzer_Analyze(t *testing.T) { { ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", Name: "golang.org/x/xerrors", - Version: "0.0.0-20200804184101-5ec99f83aff1", + Version: "v0.0.0-20200804184101-5ec99f83aff1", Relationship: types.RelationshipIndirect, Indirect: true, }, @@ -96,7 +96,7 @@ func Test_gomodAnalyzer_Analyze(t *testing.T) { { ID: "github.com/sad/sad@v0.0.1", Name: "github.com/sad/sad", - Version: "0.0.1", + Version: "v0.0.1", Relationship: types.RelationshipDirect, ExternalReferences: []types.ExternalRef{ { @@ -136,7 +136,7 @@ func Test_gomodAnalyzer_Analyze(t *testing.T) { { ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20230219131432-590b1dfb6edd", Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20230219131432-590b1dfb6edd", + Version: "v0.0.0-20230219131432-590b1dfb6edd", Relationship: types.RelationshipDirect, DependsOn: []string{ "github.com/BurntSushi/toml@v0.3.1", @@ -151,7 +151,7 @@ func Test_gomodAnalyzer_Analyze(t *testing.T) { { ID: "github.com/BurntSushi/toml@v0.3.1", Name: "github.com/BurntSushi/toml", - Version: "0.3.1", + Version: "v0.3.1", Relationship: types.RelationshipIndirect, Indirect: true, Licenses: []string{ @@ -188,7 +188,7 @@ func Test_gomodAnalyzer_Analyze(t *testing.T) { { ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20230219131432-590b1dfb6edd", Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20230219131432-590b1dfb6edd", + Version: "v0.0.0-20230219131432-590b1dfb6edd", Relationship: types.RelationshipDirect, DependsOn: []string{}, ExternalReferences: []types.ExternalRef{ diff --git a/pkg/purl/purl_test.go b/pkg/purl/purl_test.go index 25e9e7829d7b..d5ba15300393 100644 --- a/pkg/purl/purl_test.go +++ b/pkg/purl/purl_test.go @@ -809,38 +809,38 @@ func TestPackageURL_Match(t *testing.T) { }{ { name: "same purl", - constraint: "pkg:golang/github.com/aquasecurity/trivy@0.49.0", - target: "pkg:golang/github.com/aquasecurity/trivy@0.49.0", + constraint: "pkg:golang/github.com/aquasecurity/trivy@v0.49.0", + target: "pkg:golang/github.com/aquasecurity/trivy@v0.49.0", want: true, }, { name: "different type", - constraint: "pkg:golang/github.com/aquasecurity/trivy@0.49.0", + constraint: "pkg:golang/github.com/aquasecurity/trivy@v0.49.0", target: "pkg:maven/github.com/aquasecurity/trivy@0.49.0", want: false, }, { name: "different namespace", - constraint: "pkg:golang/github.com/aquasecurity/trivy@0.49.0", - target: "pkg:golang/github.com/aquasecurity2/trivy@0.49.0", + constraint: "pkg:golang/github.com/aquasecurity/trivy@v0.49.0", + target: "pkg:golang/github.com/aquasecurity2/trivy@v.49.0", want: false, }, { name: "different name", - constraint: "pkg:golang/github.com/aquasecurity/trivy@0.49.0", - target: "pkg:golang/github.com/aquasecurity/tracee@0.49.0", + constraint: "pkg:golang/github.com/aquasecurity/trivy@v0.49.0", + target: "pkg:golang/github.com/aquasecurity/tracee@v0.49.0", want: false, }, { name: "different version", - constraint: "pkg:golang/github.com/aquasecurity/trivy@0.49.0", - target: "pkg:golang/github.com/aquasecurity/trivy@0.49.1", + constraint: "pkg:golang/github.com/aquasecurity/trivy@v0.49.0", + target: "pkg:golang/github.com/aquasecurity/trivy@v0.49.1", want: false, }, { name: "version wildcard", constraint: "pkg:golang/github.com/aquasecurity/trivy", - target: "pkg:golang/github.com/aquasecurity/trivy@0.50.0", + target: "pkg:golang/github.com/aquasecurity/trivy@v0.50.0", want: true, }, { diff --git a/pkg/result/filter_test.go b/pkg/result/filter_test.go index 289ec2ee0c63..08b523dd2dde 100644 --- a/pkg/result/filter_test.go +++ b/pkg/result/filter_test.go @@ -21,16 +21,16 @@ import ( func TestFilter(t *testing.T) { var ( pkg1 = ftypes.Package{ - ID: "foo@1.2.3", + ID: "foo@v1.2.3", Name: "foo", - Version: "1.2.3", + Version: "v1.2.3", Identifier: ftypes.PkgIdentifier{ UID: "01", PURL: &packageurl.PackageURL{ Type: packageurl.TypeGolang, Namespace: "github.com/aquasecurity", Name: "foo", - Version: "1.2.3", + Version: "v1.2.3", }, }, } @@ -90,14 +90,14 @@ func TestFilter(t *testing.T) { vuln6 = types.DetectedVulnerability{ VulnerabilityID: "CVE-2019-0006", PkgName: "foo", - InstalledVersion: "1.2.3", + InstalledVersion: "v1.2.3", FixedVersion: "1.2.4", PkgIdentifier: ftypes.PkgIdentifier{ PURL: &packageurl.PackageURL{ Type: packageurl.TypeGolang, Namespace: "github.com/aquasecurity", Name: "foo", - Version: "1.2.3", + Version: "v1.2.3", }, }, Vulnerability: dbTypes.Vulnerability{ @@ -107,14 +107,14 @@ func TestFilter(t *testing.T) { vuln7 = types.DetectedVulnerability{ VulnerabilityID: "CVE-2019-0007", PkgName: "bar", - InstalledVersion: "2.3.4", + InstalledVersion: "v2.3.4", FixedVersion: "2.3.5", PkgIdentifier: ftypes.PkgIdentifier{ PURL: &packageurl.PackageURL{ Type: packageurl.TypeGolang, Namespace: "github.com/aquasecurity", Name: "bar", - Version: "2.3.4", + Version: "v2.3.4", }, }, Vulnerability: dbTypes.Vulnerability{ diff --git a/pkg/result/testdata/openvex.json b/pkg/result/testdata/openvex.json index dcdd344700c7..385f22e47deb 100644 --- a/pkg/result/testdata/openvex.json +++ b/pkg/result/testdata/openvex.json @@ -8,7 +8,7 @@ { "vulnerability": {"name": "CVE-2019-0001"}, "products": [ - {"@id": "pkg:golang/github.com/aquasecurity/foo@1.2.3"} + {"@id": "pkg:golang/github.com/aquasecurity/foo@v1.2.3"} ], "status": "not_affected", "justification": "vulnerable_code_not_in_execute_path" diff --git a/pkg/sbom/io/encode_test.go b/pkg/sbom/io/encode_test.go index 52fbed415933..5a5b821590b8 100644 --- a/pkg/sbom/io/encode_test.go +++ b/pkg/sbom/io/encode_test.go @@ -461,7 +461,7 @@ func TestEncoder_Encode(t *testing.T) { Type: packageurl.TypeGolang, Namespace: "github.com/org", Name: "direct", - Version: "1.0.0", + Version: "v1.0.0", }, }, Relationship: ftypes.RelationshipDirect, @@ -472,28 +472,28 @@ func TestEncoder_Encode(t *testing.T) { { ID: "github.com/org/indirect@v2.0.0", Name: "github.com/org/indirect", - Version: "2.0.0", + Version: "v2.0.0", Identifier: ftypes.PkgIdentifier{ UID: "955AB4E7E24AC085", PURL: &packageurl.PackageURL{ Type: packageurl.TypeGolang, Namespace: "github.com/org", Name: "indirect", - Version: "2.0.0", + Version: "v2.0.0", }, }, Relationship: ftypes.RelationshipIndirect, }, { - ID: "stdlib@1.22.1", + ID: "stdlib@v1.22.1", Name: "stdlib", - Version: "1.22.1", + Version: "v1.22.1", Identifier: ftypes.PkgIdentifier{ UID: "49728B9674E318A6", PURL: &packageurl.PackageURL{ Type: packageurl.TypeGolang, Name: "stdlib", - Version: "1.22.1", + Version: "v1.22.1", }, }, Relationship: ftypes.RelationshipDirect, @@ -561,7 +561,7 @@ func TestEncoder_Encode(t *testing.T) { uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000004"): { Type: core.TypeLibrary, Name: "github.com/org/direct", - Version: "1.0.0", + Version: "v1.0.0", SrcFile: "test", Properties: []core.Property{ { @@ -579,15 +579,15 @@ func TestEncoder_Encode(t *testing.T) { Type: packageurl.TypeGolang, Namespace: "github.com/org", Name: "direct", - Version: "1.0.0", + Version: "v1.0.0", }, - BOMRef: "pkg:golang/github.com/org/direct@1.0.0", + BOMRef: "pkg:golang/github.com/org/direct@v1.0.0", }, }, uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000005"): { Type: core.TypeLibrary, Name: "github.com/org/indirect", - Version: "2.0.0", + Version: "v2.0.0", SrcFile: "test", Properties: []core.Property{ { @@ -605,20 +605,20 @@ func TestEncoder_Encode(t *testing.T) { Type: packageurl.TypeGolang, Namespace: "github.com/org", Name: "indirect", - Version: "2.0.0", + Version: "v2.0.0", }, - BOMRef: "pkg:golang/github.com/org/indirect@2.0.0", + BOMRef: "pkg:golang/github.com/org/indirect@v2.0.0", }, }, uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000006"): { Type: core.TypeLibrary, Name: "stdlib", - Version: "1.22.1", + Version: "v1.22.1", SrcFile: "test", Properties: []core.Property{ { Name: core.PropertyPkgID, - Value: "stdlib@1.22.1", + Value: "stdlib@v1.22.1", }, { Name: core.PropertyPkgType, @@ -630,9 +630,9 @@ func TestEncoder_Encode(t *testing.T) { PURL: &packageurl.PackageURL{ Type: packageurl.TypeGolang, Name: "stdlib", - Version: "1.22.1", + Version: "v1.22.1", }, - BOMRef: "pkg:golang/stdlib@1.22.1", + BOMRef: "pkg:golang/stdlib@v1.22.1", }, }, }, diff --git a/pkg/vex/testdata/csaf-relationships.json b/pkg/vex/testdata/csaf-relationships.json index 2e823d17a2c6..18c311228206 100644 --- a/pkg/vex/testdata/csaf-relationships.json +++ b/pkg/vex/testdata/csaf-relationships.json @@ -42,7 +42,7 @@ "name": "go-direct1 v2.0.0", "product_id": "go-direct1-v2.0.0", "product_identification_helper": { - "purl": "pkg:golang/github.com/aquasecurity/go-direct1@2.0.0" + "purl": "pkg:golang/github.com/aquasecurity/go-direct1@v2.0.0" } } } @@ -65,7 +65,7 @@ "name": "go-transitive v4.0.0", "product_id": "go-transitive-v4.0.0", "product_identification_helper": { - "purl": "pkg:golang/github.com/aquasecurity/go-transitive@4.0.0" + "purl": "pkg:golang/github.com/aquasecurity/go-transitive@v4.0.0" } } } diff --git a/pkg/vex/testdata/csaf.json b/pkg/vex/testdata/csaf.json index 70afefe70205..182856f96a51 100644 --- a/pkg/vex/testdata/csaf.json +++ b/pkg/vex/testdata/csaf.json @@ -50,7 +50,7 @@ "name": "go-transitive v4.0.0", "product_id": "go-transitive-v4.0.0", "product_identification_helper": { - "purl": "pkg:golang/github.com/aquasecurity/go-transitive@4.0.0" + "purl": "pkg:golang/github.com/aquasecurity/go-transitive@v4.0.0" } } } diff --git a/pkg/vex/testdata/openvex-nested.json b/pkg/vex/testdata/openvex-nested.json index da7dd68615a5..637603d9e48c 100644 --- a/pkg/vex/testdata/openvex-nested.json +++ b/pkg/vex/testdata/openvex-nested.json @@ -11,10 +11,10 @@ }, "products": [ { - "@id": "pkg:golang/github.com/aquasecurity/go-direct1@2.0.0", + "@id": "pkg:golang/github.com/aquasecurity/go-direct1@v2.0.0", "subcomponents": [ { - "@id": "pkg:golang/github.com/aquasecurity/go-transitive@4.0.0" + "@id": "pkg:golang/github.com/aquasecurity/go-transitive@v4.0.0" } ] } diff --git a/pkg/vex/vex_test.go b/pkg/vex/vex_test.go index 4a9686972a5e..bc7a5c069402 100644 --- a/pkg/vex/vex_test.go +++ b/pkg/vex/vex_test.go @@ -58,9 +58,9 @@ var ( }, } goModulePackage = ftypes.Package{ - ID: "github.com/aquasecurity/go-module@1.0.0", + ID: "github.com/aquasecurity/go-module@v1.0.0", Name: "github.com/aquasecurity/go-module", - Version: "1.0.0", + Version: "v1.0.0", Relationship: ftypes.RelationshipRoot, Identifier: ftypes.PkgIdentifier{ UID: "03", @@ -68,14 +68,14 @@ var ( Type: packageurl.TypeGolang, Namespace: "github.com/aquasecurity", Name: "go-module", - Version: "1.0.0", + Version: "v1.0.0", }, }, } goDirectPackage1 = ftypes.Package{ - ID: "github.com/aquasecurity/go-direct1@2.0.0", + ID: "github.com/aquasecurity/go-direct1@v2.0.0", Name: "github.com/aquasecurity/go-direct1", - Version: "2.0.0", + Version: "v2.0.0", Relationship: ftypes.RelationshipDirect, Identifier: ftypes.PkgIdentifier{ UID: "04", @@ -83,14 +83,14 @@ var ( Type: packageurl.TypeGolang, Namespace: "github.com/aquasecurity", Name: "go-direct1", - Version: "2.0.0", + Version: "v2.0.0", }, }, } goDirectPackage2 = ftypes.Package{ - ID: "github.com/aquasecurity/go-direct2@3.0.0", + ID: "github.com/aquasecurity/go-direct2@v3.0.0", Name: "github.com/aquasecurity/go-direct2", - Version: "3.0.0", + Version: "v3.0.0", Relationship: ftypes.RelationshipDirect, Identifier: ftypes.PkgIdentifier{ UID: "05", @@ -98,14 +98,14 @@ var ( Type: packageurl.TypeGolang, Namespace: "github.com/aquasecurity", Name: "go-direct2", - Version: "3.0.0", + Version: "v3.0.0", }, }, } goTransitivePackage = ftypes.Package{ - ID: "github.com/aquasecurity/go-transitive@4.0.0", + ID: "github.com/aquasecurity/go-transitive@v4.0.0", Name: "github.com/aquasecurity/go-transitive", - Version: "4.0.0", + Version: "v4.0.0", Relationship: ftypes.RelationshipIndirect, Identifier: ftypes.PkgIdentifier{ UID: "06", @@ -113,7 +113,7 @@ var ( Type: packageurl.TypeGolang, Namespace: "github.com/aquasecurity", Name: "go-transitive", - Version: "4.0.0", + Version: "v4.0.0", }, }, } @@ -646,9 +646,9 @@ func goSinglePathResult(result types.Result) types.Result { result.Type = ftypes.GoModule result.Class = types.ClassLangPkg - // - pkg:golang/github.com/aquasecurity/go-module@1.0.0 - // - pkg:golang/github.com/aquasecurity/go-direct1@2.0.0 - // - pkg:golang/github.com/aquasecurity/go-transitive@4.0.0 + // - pkg:golang/github.com/aquasecurity/go-module@v1.0.0 + // - pkg:golang/github.com/aquasecurity/go-direct1@v2.0.0 + // - pkg:golang/github.com/aquasecurity/go-transitive@v4.0.0 goModule := clonePackage(goModulePackage) goDirect1 := clonePackage(goDirectPackage1) goTransitive := clonePackage(goTransitivePackage) @@ -667,11 +667,11 @@ func goMultiPathResult(result types.Result) types.Result { result.Type = ftypes.GoModule result.Class = types.ClassLangPkg - // - pkg:golang/github.com/aquasecurity/go-module@2.0.0 - // - pkg:golang/github.com/aquasecurity/go-direct1@3.0.0 - // - pkg:golang/github.com/aquasecurity/go-transitive@5.0.0 - // - pkg:golang/github.com/aquasecurity/go-direct2@4.0.0 - // - pkg:golang/github.com/aquasecurity/go-transitive@5.0.0 + // - pkg:golang/github.com/aquasecurity/go-module@v2.0.0 + // - pkg:golang/github.com/aquasecurity/go-direct1@v3.0.0 + // - pkg:golang/github.com/aquasecurity/go-transitive@v5.0.0 + // - pkg:golang/github.com/aquasecurity/go-direct2@v4.0.0 + // - pkg:golang/github.com/aquasecurity/go-transitive@v5.0.0 goModule := clonePackage(goModulePackage) goDirect1 := clonePackage(goDirectPackage1) goDirect2 := clonePackage(goDirectPackage2) From 194d4abb03ba72a6f38287fa7c0e5bef6217c7bc Mon Sep 17 00:00:00 2001 From: simar7 <1254783+simar7@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:37:21 -0600 Subject: [PATCH 77/94] chore(deps): Bump trivy-checks (#7819) --- go.mod | 8 +-- go.sum | 26 +++++---- integration/repo_test.go | 9 --- .../dockerfile-custom-policies.json.golden | 2 +- .../dockerfile-rule-exception.json.golden | 57 ------------------- integration/testdata/dockerfile.json.golden | 2 +- .../dockerfile_file_pattern.json.golden | 2 +- .../fixtures/repo/rule-exception/Dockerfile | 4 -- .../repo/rule-exception/policy/exception.rego | 15 ----- integration/testdata/helm.json.golden | 5 +- .../testdata/helm_testchart.json.golden | 9 +-- .../helm_testchart.overridden.json.golden | 9 +-- 12 files changed, 34 insertions(+), 114 deletions(-) delete mode 100644 integration/testdata/dockerfile-rule-exception.json.golden delete mode 100644 integration/testdata/fixtures/repo/rule-exception/Dockerfile delete mode 100644 integration/testdata/fixtures/repo/rule-exception/policy/exception.rego diff --git a/go.mod b/go.mod index efc9daa926c9..f4a034a8063a 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/aquasecurity/table v1.8.0 github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8 github.com/aquasecurity/tml v0.6.1 - github.com/aquasecurity/trivy-checks v1.1.0 + github.com/aquasecurity/trivy-checks v1.2.2 github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1 github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241029051843-2606b7e0f0b4 @@ -124,7 +124,7 @@ require ( golang.org/x/mod v0.21.0 golang.org/x/net v0.29.0 golang.org/x/sync v0.8.0 - golang.org/x/term v0.24.0 + golang.org/x/term v0.25.0 golang.org/x/text v0.18.0 golang.org/x/vuln v1.1.3 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 @@ -385,7 +385,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sys v0.25.0 // indirect + golang.org/x/sys v0.26.0 // indirect golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 // indirect golang.org/x/time v0.6.0 // indirect golang.org/x/tools v0.24.0 // indirect @@ -416,7 +416,7 @@ require ( modernc.org/memory v1.8.0 // indirect modernc.org/strutil v1.2.0 // indirect modernc.org/token v1.1.0 // indirect - mvdan.cc/sh/v3 v3.8.0 // indirect + mvdan.cc/sh/v3 v3.10.0 // indirect oras.land/oras-go v1.2.5 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/kustomize/api v0.17.2 // indirect diff --git a/go.sum b/go.sum index 153c1ab02dea..5eadfbf83818 100644 --- a/go.sum +++ b/go.sum @@ -349,8 +349,8 @@ github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8 h1:b43UVqY github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8/go.mod h1:wXA9k3uuaxY3yu7gxrxZDPo/04FEMJtwyecdAlYrEIo= github.com/aquasecurity/tml v0.6.1 h1:y2ZlGSfrhnn7t4ZJ/0rotuH+v5Jgv6BDDO5jB6A9gwo= github.com/aquasecurity/tml v0.6.1/go.mod h1:OnYMWY5lvI9ejU7yH9LCberWaaTBW7hBFsITiIMY2yY= -github.com/aquasecurity/trivy-checks v1.1.0 h1:I0tVOK8dG/KHrWsqfGNYp2uD/i0f+yS7Je31F+LIUqQ= -github.com/aquasecurity/trivy-checks v1.1.0/go.mod h1:tVzhU0gajD3GmxKPLn/BHR8ZeUquc5ajQTmAsi0kCCU= +github.com/aquasecurity/trivy-checks v1.2.2 h1:EVHi0gthYzDLfqdAqBBwVGfg2l/gdZ622pIlC9rP+lU= +github.com/aquasecurity/trivy-checks v1.2.2/go.mod h1:TNV0QNVFyBIkt865eO2PtfpubmHt3Ve19Klny//SWIU= github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1 h1:G0gnacAORRUqz2Tm5MqivSpldY2GZ74ijhJcMsae+sA= github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1/go.mod h1:PYkSRx4dlgFATEt+okGwibvbxVEtqsOdH+vX/saACYE= github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 h1:JVgBIuIYbwG+ekC5lUHUpGJboPYiCcxiz06RCtz8neI= @@ -510,8 +510,8 @@ github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHf github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= -github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0= +github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/csaf-poc/csaf_distribution/v3 v3.0.0 h1:ob9+Fmpff0YWgTP3dYaw7G2hKQ9cegh9l3zksc+q3sM= github.com/csaf-poc/csaf_distribution/v3 v3.0.0/go.mod h1:uilCTiNKivq+6zrDvjtZaUeLk70oe21iwKivo6ILwlQ= github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 h1:2Dx4IHfC1yHWI12AxQDJM1QbRCDfk6M+blLzlZCXdrc= @@ -683,6 +683,8 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91 github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtPsPm2S9NAZ5nl9U= github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= @@ -1204,8 +1206,8 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rubenv/sql-migrate v1.7.0 h1:HtQq1xyTN2ISmQDggnh0c9U3JlP8apWh8YO2jzlXpTI= github.com/rubenv/sql-migrate v1.7.0/go.mod h1:S4wtDEG1CKn+0ShpTtzWhFpHHI5PvCUtiGI+C+Z2THE= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1703,8 +1705,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 h1:FemxDzfMUcK2f3YY4H+05K9CDzbSVr2+q/JKN45pey0= golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1715,8 +1717,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2124,8 +2126,8 @@ modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -mvdan.cc/sh/v3 v3.8.0 h1:ZxuJipLZwr/HLbASonmXtcvvC9HXY9d2lXZHnKGjFc8= -mvdan.cc/sh/v3 v3.8.0/go.mod h1:w04623xkgBVo7/IUK89E0g8hBykgEpN0vgOj3RJr6MY= +mvdan.cc/sh/v3 v3.10.0 h1:v9z7N1DLZ7owyLM/SXZQkBSXcwr2IGMm2LY2pmhVXj4= +mvdan.cc/sh/v3 v3.10.0/go.mod h1:z/mSSVyLFGZzqb3ZIKojjyqIx/xbmz/UHdCSv9HmqXY= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/integration/repo_test.go b/integration/repo_test.go index 6b4e3a338457..87c27684d3ab 100644 --- a/integration/repo_test.go +++ b/integration/repo_test.go @@ -300,15 +300,6 @@ func TestRepository(t *testing.T) { }, golden: "testdata/dockerfile_file_pattern.json.golden", }, - { - name: "dockerfile with rule exception", - args: args{ - scanner: types.MisconfigScanner, - policyPaths: []string{"testdata/fixtures/repo/rule-exception/policy"}, - input: "testdata/fixtures/repo/rule-exception", - }, - golden: "testdata/dockerfile-rule-exception.json.golden", - }, { name: "dockerfile with custom policies", args: args{ diff --git a/integration/testdata/dockerfile-custom-policies.json.golden b/integration/testdata/dockerfile-custom-policies.json.golden index 2cbda6f16703..64ce52ba64b3 100644 --- a/integration/testdata/dockerfile-custom-policies.json.golden +++ b/integration/testdata/dockerfile-custom-policies.json.golden @@ -21,7 +21,7 @@ "Class": "config", "Type": "dockerfile", "MisconfSummary": { - "Successes": 27, + "Successes": 28, "Failures": 2 }, "Misconfigurations": [ diff --git a/integration/testdata/dockerfile-rule-exception.json.golden b/integration/testdata/dockerfile-rule-exception.json.golden deleted file mode 100644 index eedcb902e145..000000000000 --- a/integration/testdata/dockerfile-rule-exception.json.golden +++ /dev/null @@ -1,57 +0,0 @@ -{ - "SchemaVersion": 2, - "CreatedAt": "2021-08-25T12:20:30.000000005Z", - "ArtifactName": "testdata/fixtures/repo/rule-exception", - "ArtifactType": "repository", - "Metadata": { - "ImageConfig": { - "architecture": "", - "created": "0001-01-01T00:00:00Z", - "os": "", - "rootfs": { - "type": "", - "diff_ids": null - }, - "config": {} - } - }, - "Results": [ - { - "Target": "Dockerfile", - "Class": "config", - "Type": "dockerfile", - "MisconfSummary": { - "Successes": 26, - "Failures": 1 - }, - "Misconfigurations": [ - { - "Type": "Dockerfile Security Check", - "ID": "DS002", - "AVDID": "AVD-DS-0002", - "Title": "Image user should not be 'root'", - "Description": "Running containers with 'root' user can lead to a container escape situation. It is a best practice to run containers as non-root users, which can be done by adding a 'USER' statement to the Dockerfile.", - "Message": "Specify at least 1 USER command in Dockerfile with non-root user as argument", - "Namespace": "builtin.dockerfile.DS002", - "Query": "data.builtin.dockerfile.DS002.deny", - "Resolution": "Add 'USER \u003cnon root user name\u003e' line to the Dockerfile", - "Severity": "HIGH", - "PrimaryURL": "https://avd.aquasec.com/misconfig/ds002", - "References": [ - "https://docs.docker.com/develop/develop-images/dockerfile_best-practices/", - "https://avd.aquasec.com/misconfig/ds002" - ], - "Status": "FAIL", - "Layer": {}, - "CauseMetadata": { - "Provider": "Dockerfile", - "Service": "general", - "Code": { - "Lines": null - } - } - } - ] - } - ] -} diff --git a/integration/testdata/dockerfile.json.golden b/integration/testdata/dockerfile.json.golden index 834b110404c1..fd1fcbfceec8 100644 --- a/integration/testdata/dockerfile.json.golden +++ b/integration/testdata/dockerfile.json.golden @@ -21,7 +21,7 @@ "Class": "config", "Type": "dockerfile", "MisconfSummary": { - "Successes": 26, + "Successes": 27, "Failures": 1 }, "Misconfigurations": [ diff --git a/integration/testdata/dockerfile_file_pattern.json.golden b/integration/testdata/dockerfile_file_pattern.json.golden index ed917023bc4b..adcd916456d5 100644 --- a/integration/testdata/dockerfile_file_pattern.json.golden +++ b/integration/testdata/dockerfile_file_pattern.json.golden @@ -21,7 +21,7 @@ "Class": "config", "Type": "dockerfile", "MisconfSummary": { - "Successes": 26, + "Successes": 27, "Failures": 1 }, "Misconfigurations": [ diff --git a/integration/testdata/fixtures/repo/rule-exception/Dockerfile b/integration/testdata/fixtures/repo/rule-exception/Dockerfile deleted file mode 100644 index 5bcf55456482..000000000000 --- a/integration/testdata/fixtures/repo/rule-exception/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM alpine:3.13 -LABEL user.root="allow" - -HEALTHCHECK NONE \ No newline at end of file diff --git a/integration/testdata/fixtures/repo/rule-exception/policy/exception.rego b/integration/testdata/fixtures/repo/rule-exception/policy/exception.rego deleted file mode 100644 index 224f626021e4..000000000000 --- a/integration/testdata/fixtures/repo/rule-exception/policy/exception.rego +++ /dev/null @@ -1,15 +0,0 @@ -package builtin.dockerfile.DS002 - -exception[rules] { - instruction := input.stages[_][_] - instruction.Cmd == "label" - - key := instruction.Value[i] - i % 2 == 0 - key == "user.root" - - value := instruction.Value[plus(i, 1)] - value == "\"allow\"" - - rules = [""] -} diff --git a/integration/testdata/helm.json.golden b/integration/testdata/helm.json.golden index 8b9ccb11bc9c..36ac8cf19935 100644 --- a/integration/testdata/helm.json.golden +++ b/integration/testdata/helm.json.golden @@ -21,7 +21,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 80, + "Successes": 79, "Failures": 14 }, "Misconfigurations": [ @@ -889,10 +889,11 @@ "Namespace": "builtin.kubernetes.KSV117", "Query": "data.builtin.kubernetes.KSV117.deny", "Resolution": "Do not map the container ports to privileged host ports when starting a container.", - "Severity": "HIGH", + "Severity": "MEDIUM", "PrimaryURL": "https://avd.aquasec.com/misconfig/ksv117", "References": [ "https://kubernetes.io/docs/concepts/security/pod-security-standards/", + "https://www.stigviewer.com/stig/kubernetes/2022-12-02/finding/V-242414", "https://avd.aquasec.com/misconfig/ksv117" ], "Status": "FAIL", diff --git a/integration/testdata/helm_testchart.json.golden b/integration/testdata/helm_testchart.json.golden index 886b0a702496..478bcea3b672 100644 --- a/integration/testdata/helm_testchart.json.golden +++ b/integration/testdata/helm_testchart.json.golden @@ -21,7 +21,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 90, + "Successes": 89, "Failures": 4 }, "Misconfigurations": [ @@ -317,10 +317,11 @@ "Namespace": "builtin.kubernetes.KSV117", "Query": "data.builtin.kubernetes.KSV117.deny", "Resolution": "Do not map the container ports to privileged host ports when starting a container.", - "Severity": "HIGH", + "Severity": "MEDIUM", "PrimaryURL": "https://avd.aquasec.com/misconfig/ksv117", "References": [ "https://kubernetes.io/docs/concepts/security/pod-security-standards/", + "https://www.stigviewer.com/stig/kubernetes/2022-12-02/finding/V-242414", "https://avd.aquasec.com/misconfig/ksv117" ], "Status": "FAIL", @@ -340,7 +341,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 61, + "Successes": 60, "Failures": 0 } }, @@ -349,7 +350,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 60, + "Successes": 59, "Failures": 0 } } diff --git a/integration/testdata/helm_testchart.overridden.json.golden b/integration/testdata/helm_testchart.overridden.json.golden index 354cb3cbf786..36710b35734e 100644 --- a/integration/testdata/helm_testchart.overridden.json.golden +++ b/integration/testdata/helm_testchart.overridden.json.golden @@ -21,7 +21,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 88, + "Successes": 87, "Failures": 6 }, "Misconfigurations": [ @@ -544,10 +544,11 @@ "Namespace": "builtin.kubernetes.KSV117", "Query": "data.builtin.kubernetes.KSV117.deny", "Resolution": "Do not map the container ports to privileged host ports when starting a container.", - "Severity": "HIGH", + "Severity": "MEDIUM", "PrimaryURL": "https://avd.aquasec.com/misconfig/ksv117", "References": [ "https://kubernetes.io/docs/concepts/security/pod-security-standards/", + "https://www.stigviewer.com/stig/kubernetes/2022-12-02/finding/V-242414", "https://avd.aquasec.com/misconfig/ksv117" ], "Status": "FAIL", @@ -567,7 +568,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 61, + "Successes": 60, "Failures": 0 } }, @@ -576,7 +577,7 @@ "Class": "config", "Type": "helm", "MisconfSummary": { - "Successes": 60, + "Successes": 59, "Failures": 0 } } From 7654b2e27e8af2d71586374d3a8c254d46f2416a Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Thu, 31 Oct 2024 15:04:52 +0600 Subject: [PATCH 78/94] docs: add example of creating whitelist of checks (#7821) Signed-off-by: nikpivkin --- docs/docs/configuration/filtering.md | 4 ++-- .../ignore-policies}/advanced.rego | 0 .../ignore-policies}/basic.rego | 0 examples/ignore-policies/whitelist.rego | 13 +++++++++++++ 4 files changed, 15 insertions(+), 2 deletions(-) rename {contrib/example_policy => examples/ignore-policies}/advanced.rego (100%) rename {contrib/example_policy => examples/ignore-policies}/basic.rego (100%) create mode 100644 examples/ignore-policies/whitelist.rego diff --git a/docs/docs/configuration/filtering.md b/docs/docs/configuration/filtering.md index 22fbe2d7a24d..095e5c3bb559 100644 --- a/docs/docs/configuration/filtering.md +++ b/docs/docs/configuration/filtering.md @@ -477,13 +477,13 @@ ignore { ``` ```bash -trivy image --ignore-policy contrib/example_policy/basic.rego centos:7 +trivy image --ignore-policy examples/ignore-policies/basic.rego centos:7 ``` For more advanced use cases, there is a built-in Rego library with helper functions that you can import into your policy using: `import data.lib.trivy`. More info about the helper functions are in the library [here](https://github.com/aquasecurity/trivy/tree/{{ git.tag }}/pkg/result/module.go). -You can find more example checks [here](https://github.com/aquasecurity/trivy/tree/{{ git.tag }}/pkg/result/module.go) +You can create a whitelist of checks using Rego, see the detailed [example](https://github.com/aquasecurity/trivy/tree/{{ git.tag }}/examples/ignore-policies/whitelist.rego). Additional examples are available [here](https://github.com/aquasecurity/trivy/tree/{{ git.tag }}/examples/ignore-policies). ### By Vulnerability Exploitability Exchange (VEX) | Scanner | Supported | diff --git a/contrib/example_policy/advanced.rego b/examples/ignore-policies/advanced.rego similarity index 100% rename from contrib/example_policy/advanced.rego rename to examples/ignore-policies/advanced.rego diff --git a/contrib/example_policy/basic.rego b/examples/ignore-policies/basic.rego similarity index 100% rename from contrib/example_policy/basic.rego rename to examples/ignore-policies/basic.rego diff --git a/examples/ignore-policies/whitelist.rego b/examples/ignore-policies/whitelist.rego new file mode 100644 index 000000000000..51a75c37c72f --- /dev/null +++ b/examples/ignore-policies/whitelist.rego @@ -0,0 +1,13 @@ +package trivy + +import rego.v1 + +allowed_checks := { + "AVD-AWS-0089" +} + +default ignore := false + +ignore if not is_check_allowed + +is_check_allowed if input.AVDID in allowed_checks \ No newline at end of file From dc44946881a9d1c1ef4e655114e9691e828b810d Mon Sep 17 00:00:00 2001 From: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:41:24 +0600 Subject: [PATCH 79/94] docs(java): add info about supported scopes (#7842) --- docs/docs/coverage/language/java.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docs/coverage/language/java.md b/docs/docs/coverage/language/java.md index 0ee39bbd3155..30aca897670a 100644 --- a/docs/docs/coverage/language/java.md +++ b/docs/docs/coverage/language/java.md @@ -69,6 +69,9 @@ The vulnerability database will be downloaded anyway. !!! Warning Trivy may skip some dependencies (that were not found on your local machine) when the `--offline-scan` flag is passed. +### supported scopes +Trivy only scans `import`, `compile`, `runtime` and empty [maven scopes][maven-scopes]. Other scopes and `Optional` dependencies are not currently being analyzed. + ### empty dependency version There are cases when Trivy cannot determine the version of dependencies: @@ -128,6 +131,7 @@ Make sure that you have cache[^8] directory to find licenses from `*.pom` depend [maven-invoker-plugin]: https://maven.apache.org/plugins/maven-invoker-plugin/usage.html [maven-central]: https://repo.maven.apache.org/maven2/ [maven-pom-repos]: https://maven.apache.org/settings.html#repositories +[maven-scopes]: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope [sbt-dependency-lock]: https://stringbean.github.io/sbt-dependency-lock [detection-priority]: ../../scanner/vulnerability.md#detection-priority [version-requirement]: https://maven.apache.org/pom.html#dependency-version-requirement-specification From 5e78b6c12fb5740c12dedeea3d335d48ec2f752b Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Thu, 31 Oct 2024 14:41:02 +0400 Subject: [PATCH 80/94] feat(db): append errors (#7843) Signed-off-by: knqyf263 --- pkg/oci/artifact.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/oci/artifact.go b/pkg/oci/artifact.go index 416952578918..8ed7dcdad03d 100644 --- a/pkg/oci/artifact.go +++ b/pkg/oci/artifact.go @@ -12,6 +12,7 @@ import ( "github.com/google/go-containerregistry/pkg/name" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/remote/transport" + "github.com/hashicorp/go-multierror" "github.com/samber/lo" "golang.org/x/xerrors" @@ -224,6 +225,7 @@ func NewArtifacts(repos []name.Reference, opt types.RegistryOptions, opts ...Opt // Download downloads artifacts until one of them succeeds. // Attempts to download next artifact if the first one fails due to a temporary error. func (a Artifacts) Download(ctx context.Context, dst string, opt DownloadOption) error { + var errs error for i, art := range a { log.InfoContext(ctx, "Downloading artifact...", log.String("repo", art.repository)) err := art.Download(ctx, dst, opt) @@ -239,9 +241,10 @@ func (a Artifacts) Download(ctx context.Context, dst string, opt DownloadOption) if i < len(a)-1 { log.InfoContext(ctx, "Trying to download artifact from other repository...") } + errs = multierror.Append(errs, err) } - return xerrors.New("failed to download artifact from any source") + return xerrors.Errorf("failed to download artifact from any source: %w", errs) } func shouldTryOtherRepo(err error) bool { From 7632625be2c4aa6f18e286baa5466b3dd885dddc Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Thu, 31 Oct 2024 16:08:47 +0400 Subject: [PATCH 81/94] chore: lint `errors.Join` (#7845) Signed-off-by: knqyf263 --- misc/lint/rules.go | 10 ++++++++++ pkg/iac/scanners/cloudformation/parser/parser.go | 11 +++++------ pkg/iac/terraform/block.go | 15 ++++++++------- pkg/report/writer.go | 4 ++-- pkg/vex/repo/repo.go | 3 ++- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/misc/lint/rules.go b/misc/lint/rules.go index e477175a244f..4f1b098535ec 100644 --- a/misc/lint/rules.go +++ b/misc/lint/rules.go @@ -20,3 +20,13 @@ func initializeMaps(m dsl.Matcher) { Suggest(`make(map[$key]$value)`). Report(`replace '$$' with 'make(map[$key]$value)`) } + +// While errors.Join from standard library can combine multiple errors, +// we use hashicorp/go-multierror for more user-friendly error outputs. +func errorsJoin(m dsl.Matcher) { + m.Match(`errors.Join($x...)`). + Report("use github.com/hashicorp/go-multierror.Append instead of errors.Join.") + + m.Match(`errors.Join($*args)`). + Report("use github.com/hashicorp/go-multierror.Append instead of errors.Join.") +} diff --git a/pkg/iac/scanners/cloudformation/parser/parser.go b/pkg/iac/scanners/cloudformation/parser/parser.go index 40d0035f6cd2..696dfcf16349 100644 --- a/pkg/iac/scanners/cloudformation/parser/parser.go +++ b/pkg/iac/scanners/cloudformation/parser/parser.go @@ -3,13 +3,13 @@ package parser import ( "context" "encoding/json" - "errors" "fmt" "io" "io/fs" "path/filepath" "strings" + "github.com/hashicorp/go-multierror" "github.com/liamg/jfather" "gopkg.in/yaml.v3" @@ -171,18 +171,17 @@ func (p *Parser) parseParams() error { params := make(Parameters) - var errs []error - + var errs error for _, path := range p.parameterFiles { if parameters, err := p.parseParametersFile(path); err != nil { - errs = append(errs, err) + errs = multierror.Append(errs, err) } else { params.Merge(parameters) } } - if len(errs) != 0 { - return errors.Join(errs...) + if errs != nil { + return errs } params.Merge(p.parameters) diff --git a/pkg/iac/terraform/block.go b/pkg/iac/terraform/block.go index dd6d8446c124..348f938d4559 100644 --- a/pkg/iac/terraform/block.go +++ b/pkg/iac/terraform/block.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/google/uuid" + "github.com/hashicorp/go-multierror" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/zclconf/go-cty/cty" @@ -600,14 +601,14 @@ func (b *Block) IsNotNil() bool { func (b *Block) ExpandBlock() error { var ( expanded []*Block - errs []error + errs error ) for _, child := range b.childBlocks { if child.Type() == "dynamic" { blocks, err := child.expandDynamic() if err != nil { - errs = append(errs, err) + errs = multierror.Append(errs, err) continue } expanded = append(expanded, blocks...) @@ -618,7 +619,7 @@ func (b *Block) ExpandBlock() error { b.injectBlock(block) } - return errors.Join(errs...) + return errs } func (b *Block) expandDynamic() ([]*Block, error) { @@ -638,7 +639,7 @@ func (b *Block) expandDynamic() ([]*Block, error) { var ( expanded []*Block - errs []error + errs error ) forEachVal.ForEachElement(func(key, val cty.Value) (stop bool) { @@ -648,7 +649,7 @@ func (b *Block) expandDynamic() ([]*Block, error) { iteratorName, err := b.iteratorName(realBlockType) if err != nil { - errs = append(errs, err) + errs = multierror.Append(errs, err) return } @@ -664,7 +665,7 @@ func (b *Block) expandDynamic() ([]*Block, error) { inherited.hclBlock.Labels = []string{} inherited.hclBlock.Type = realBlockType if err := inherited.ExpandBlock(); err != nil { - errs = append(errs, err) + errs = multierror.Append(errs, err) return } expanded = append(expanded, inherited) @@ -676,7 +677,7 @@ func (b *Block) expandDynamic() ([]*Block, error) { b.markExpanded() } - return expanded, errors.Join(errs...) + return expanded, errs } func (b *Block) validateForEach() (cty.Value, error) { diff --git a/pkg/report/writer.go b/pkg/report/writer.go index a5b7ae231599..f25d579d66ef 100644 --- a/pkg/report/writer.go +++ b/pkg/report/writer.go @@ -2,10 +2,10 @@ package report import ( "context" - "errors" "io" "strings" + "github.com/hashicorp/go-multierror" "golang.org/x/xerrors" cr "github.com/aquasecurity/trivy/pkg/compliance/report" @@ -32,7 +32,7 @@ func Write(ctx context.Context, report types.Report, option flag.Options) (err e } defer func() { if cerr := cleanup(); cerr != nil { - err = errors.Join(err, cerr) + err = multierror.Append(err, cerr) } }() diff --git a/pkg/vex/repo/repo.go b/pkg/vex/repo/repo.go index 433b8224c20e..b9637c229ee9 100644 --- a/pkg/vex/repo/repo.go +++ b/pkg/vex/repo/repo.go @@ -11,6 +11,7 @@ import ( "time" "github.com/hashicorp/go-getter" + "github.com/hashicorp/go-multierror" "github.com/samber/lo" "golang.org/x/xerrors" @@ -256,7 +257,7 @@ func (r *Repository) download(ctx context.Context, ver Version, dst string, opts etag = etags[loc.URL] // Keep the old ETag // Update last updated time so that Trivy will not try to download the same URL soon case err != nil: - errs = errors.Join(errs, err) + errs = multierror.Append(errs, err) continue // Try the next location default: // Successfully downloaded From efec32669b79aba5ae61771e2d655e45e313ac2f Mon Sep 17 00:00:00 2001 From: Aqua Security automated builds <54269356+aqua-bot@users.noreply.github.com> Date: Fri, 1 Nov 2024 06:01:54 +0200 Subject: [PATCH 82/94] release: v0.57.0 [main] (#7710) --- .release-please-manifest.json | 2 +- CHANGELOG.md | 46 +++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 208746a81be3..0fd1f968a6d2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{".":"0.56.0"} +{".":"0.57.0"} diff --git a/CHANGELOG.md b/CHANGELOG.md index afc44ba7a956..f4bad92b11d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,51 @@ # Changelog +## [0.57.0](https://github.com/aquasecurity/trivy/compare/v0.56.0...v0.57.0) (2024-10-31) + + +### ⚠ BREAKING CHANGES + +* **k8s:** support k8s multi container ([#7444](https://github.com/aquasecurity/trivy/issues/7444)) + +### Features + +* add end of life date for Ubuntu 24.10 ([#7787](https://github.com/aquasecurity/trivy/issues/7787)) ([ad3c09e](https://github.com/aquasecurity/trivy/commit/ad3c09e006e134f3c5b879ffc34ce9895a8c860f)) +* **cli:** add `trivy auth` ([#7664](https://github.com/aquasecurity/trivy/issues/7664)) ([27117f8](https://github.com/aquasecurity/trivy/commit/27117f81d52483c3ceec56fe56ac298e242fbc9a)) +* **cli:** error out when ignore file cannot be found ([#7624](https://github.com/aquasecurity/trivy/issues/7624)) ([cb0b3a9](https://github.com/aquasecurity/trivy/commit/cb0b3a9279b31810ecd686a385e5140e567ce86f)) +* **cli:** rename `trivy auth` to `trivy registry` ([#7727](https://github.com/aquasecurity/trivy/issues/7727)) ([633a7ab](https://github.com/aquasecurity/trivy/commit/633a7abeea4287899392a24f2705f96dfeb7e312)) +* **cyclonedx:** add file checksums to `CycloneDX` reports ([#7507](https://github.com/aquasecurity/trivy/issues/7507)) ([c225883](https://github.com/aquasecurity/trivy/commit/c225883649f58128a99fa2c1cef327d0e57940be)) +* **db:** append errors ([#7843](https://github.com/aquasecurity/trivy/issues/7843)) ([5e78b6c](https://github.com/aquasecurity/trivy/commit/5e78b6c12fb5740c12dedeea3d335d48ec2f752b)) +* **misconf:** export unresolvable field of IaC types to Rego ([#7765](https://github.com/aquasecurity/trivy/issues/7765)) ([9514148](https://github.com/aquasecurity/trivy/commit/9514148767865baddd73a49245385574927f7a74)) +* **misconf:** public network support for Azure Storage Account ([#7601](https://github.com/aquasecurity/trivy/issues/7601)) ([ad91412](https://github.com/aquasecurity/trivy/commit/ad914123c4d203af1e1da6b7e2d3e49d9d3831d8)) +* **misconf:** Show misconfig ID in output ([#7762](https://github.com/aquasecurity/trivy/issues/7762)) ([f75c0d1](https://github.com/aquasecurity/trivy/commit/f75c0d1f0069d4856cb4826d6049f32c5b9409d9)) +* **misconf:** ssl_mode support for GCP SQL DB instance ([#7564](https://github.com/aquasecurity/trivy/issues/7564)) ([2eaa17e](https://github.com/aquasecurity/trivy/commit/2eaa17e0717940b27a79050e2efd9213b71178c9)) +* **parser:** ignore white space in pom.xml files ([#7747](https://github.com/aquasecurity/trivy/issues/7747)) ([a7baa93](https://github.com/aquasecurity/trivy/commit/a7baa93b00b8636aa097e64cdb8eed97dbd68511)) +* **report:** update gitlab template to populate operating_system value ([#7735](https://github.com/aquasecurity/trivy/issues/7735)) ([c0d79fa](https://github.com/aquasecurity/trivy/commit/c0d79fa09e645f3a3dbff878e393b8631fb17b64)) + + +### Bug Fixes + +* **cli:** `clean --all` deletes only relevant dirs ([#7704](https://github.com/aquasecurity/trivy/issues/7704)) ([672e886](https://github.com/aquasecurity/trivy/commit/672e886aed152ae0f09a16941706746f3053ca94)) +* **cli:** add config name to skip-policy-update alias ([#7820](https://github.com/aquasecurity/trivy/issues/7820)) ([b661d68](https://github.com/aquasecurity/trivy/commit/b661d680ff0372c8e4beea0db13bf69d6a2203a8)) +* **db:** fix javadb downloading error handling ([#7642](https://github.com/aquasecurity/trivy/issues/7642)) ([2c87f0c](https://github.com/aquasecurity/trivy/commit/2c87f0cb794acd77446a273582ba1a45b9f18980)) +* enable usestdlibvars linter ([#7770](https://github.com/aquasecurity/trivy/issues/7770)) ([57e24aa](https://github.com/aquasecurity/trivy/commit/57e24aa85382f749df7f673e241caaf3fcbb45cb)) +* **go:** Do not trim v prefix from versions in Go Mod Analyzer ([#7733](https://github.com/aquasecurity/trivy/issues/7733)) ([e872ec0](https://github.com/aquasecurity/trivy/commit/e872ec006c0745a5a142728af0096c6d6bb9ddf3)) +* **helm:** properly handle multiple archived dependencies ([#7782](https://github.com/aquasecurity/trivy/issues/7782)) ([6fab88d](https://github.com/aquasecurity/trivy/commit/6fab88dd56c257ef2cc63b617c2a5decb1c4cf98)) +* **java:** correctly inherit `version` and `scope` from upper/root `depManagement` and `dependencies` into parents ([#7541](https://github.com/aquasecurity/trivy/issues/7541)) ([778df82](https://github.com/aquasecurity/trivy/commit/778df828eaad9827cb833c6285058a33aa2b83ca)) +* **k8s:** skip resources without misconfigs ([#7797](https://github.com/aquasecurity/trivy/issues/7797)) ([7882776](https://github.com/aquasecurity/trivy/commit/78827768a612ab305bf9c55409ce76d6774302a5)) +* **k8s:** support k8s multi container ([#7444](https://github.com/aquasecurity/trivy/issues/7444)) ([c434775](https://github.com/aquasecurity/trivy/commit/c4347759234dcb5f372b07f92fb4230ef391d710)) +* **k8s:** support kubernetes v1.31 ([#7810](https://github.com/aquasecurity/trivy/issues/7810)) ([7a4f4d8](https://github.com/aquasecurity/trivy/commit/7a4f4d8b12996687f3095a2042cdf2f5985332c9)) +* **license:** fix license normalization for Universal Permissive License ([#7766](https://github.com/aquasecurity/trivy/issues/7766)) ([f6acdf7](https://github.com/aquasecurity/trivy/commit/f6acdf713991f8ffdbe765178fcb8a9cde433cba)) +* **misconf:** change default ACL of digitalocean_spaces_bucket to private ([#7577](https://github.com/aquasecurity/trivy/issues/7577)) ([9da84f5](https://github.com/aquasecurity/trivy/commit/9da84f54fadbe6ad0d73983952e945ed63b666f3)) +* **misconf:** check if property is not nil before conversion ([#7578](https://github.com/aquasecurity/trivy/issues/7578)) ([c8c14d3](https://github.com/aquasecurity/trivy/commit/c8c14d36245623019f29d258f813d2325f7490f7)) +* **misconf:** fix for Azure Storage Account network acls adaptation ([#7602](https://github.com/aquasecurity/trivy/issues/7602)) ([35fd018](https://github.com/aquasecurity/trivy/commit/35fd018ae7ad86823f114f0ac2f1376726aee444)) +* **misconf:** properly expand dynamic blocks ([#7612](https://github.com/aquasecurity/trivy/issues/7612)) ([8d5dbc9](https://github.com/aquasecurity/trivy/commit/8d5dbc9fec3569b22ed81a03c40eaf732768718b)) +* **redhat:** include arch in PURL qualifiers ([#7654](https://github.com/aquasecurity/trivy/issues/7654)) ([a585e95](https://github.com/aquasecurity/trivy/commit/a585e95f3398631d9ad10505c5ff642fde21aef7)) +* **repo:** `git clone` output to Stderr ([#7561](https://github.com/aquasecurity/trivy/issues/7561)) ([fdf203c](https://github.com/aquasecurity/trivy/commit/fdf203cd209aeb40f454bd12d121a54d6ed7a542)) +* **report:** Fix invalid URI in SARIF report ([#7645](https://github.com/aquasecurity/trivy/issues/7645)) ([015bb88](https://github.com/aquasecurity/trivy/commit/015bb885ac414b91201fa9791eead395d878149c)) +* **sbom:** add options for DBs in private registries ([#7660](https://github.com/aquasecurity/trivy/issues/7660)) ([1f2e91b](https://github.com/aquasecurity/trivy/commit/1f2e91b02b3606dd11963002a8cfac7962f3478f)) +* **sbom:** use `Annotation` instead of `AttributionTexts` for `SPDX` formats ([#7811](https://github.com/aquasecurity/trivy/issues/7811)) ([f2bb9c6](https://github.com/aquasecurity/trivy/commit/f2bb9c6227743dd61f44eb591d4b15192fe110c6)) + ## [0.56.0](https://github.com/aquasecurity/trivy/compare/v0.55.0...v0.56.0) (2024-10-03) From 4da59bd7b621366b05480cb84ee01786bc95f2fd Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Mon, 4 Nov 2024 10:01:05 +0400 Subject: [PATCH 83/94] chore: bump golangci-lint to v1.61.0 (#7853) Signed-off-by: knqyf263 --- .github/workflows/test.yaml | 2 +- .golangci.yaml | 1 + magefiles/magefile.go | 2 +- pkg/fanal/walker/walk_test.go | 19 ++++++++++++------- pkg/plugin/index.go | 2 +- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 05edadf93331..c2af5eb66bbb 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -42,7 +42,7 @@ jobs: id: lint uses: golangci/golangci-lint-action@v6.0.1 with: - version: v1.59 + version: v1.61 args: --verbose --out-format=line-number if: matrix.operating-system == 'ubuntu-latest' diff --git a/.golangci.yaml b/.golangci.yaml index 40bfa36e1a64..b6dbc299be20 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -68,6 +68,7 @@ linters-settings: excludes: - G101 - G114 + - G115 - G204 - G304 - G402 diff --git a/magefiles/magefile.go b/magefiles/magefile.go index f70491bce2e8..5b08e907f0c0 100644 --- a/magefiles/magefile.go +++ b/magefiles/magefile.go @@ -77,7 +77,7 @@ func (Tool) Wire() error { // GolangciLint installs golangci-lint func (t Tool) GolangciLint() error { - const version = "v1.59.1" + const version = "v1.61.0" bin := filepath.Join(GOBIN, "golangci-lint") if exists(bin) && t.matchGolangciLintVersion(bin, version) { return nil diff --git a/pkg/fanal/walker/walk_test.go b/pkg/fanal/walker/walk_test.go index 09d55527c0fe..3c066529393f 100644 --- a/pkg/fanal/walker/walk_test.go +++ b/pkg/fanal/walker/walk_test.go @@ -1,7 +1,6 @@ package walker_test import ( - "fmt" "path/filepath" "testing" @@ -42,8 +41,11 @@ func TestSkipFile(t *testing.T) { }, }, { - name: "multiple skip files", - skipFiles: []string{"/etc/*/*", "/var/log/*.txt"}, + name: "multiple skip files", + skipFiles: []string{ + "/etc/*/*", + "/var/log/*.txt", + }, wants: map[string]bool{ "/etc/foo": false, "/etc/foo/bar": true, @@ -65,7 +67,7 @@ func TestSkipFile(t *testing.T) { for file, want := range tt.wants { file = filepath.ToSlash(filepath.Clean(file)) got := utils.SkipPath(file, utils.CleanSkipPaths(tt.skipFiles)) - assert.Equal(t, want, got, fmt.Sprintf("skipFiles: %s, file: %s", tt.skipFiles, file)) + assert.Equal(t, want, got, "skipFiles: %s, file: %s", tt.skipFiles, file) } }) } @@ -108,8 +110,11 @@ func TestSkipDir(t *testing.T) { }, }, { - name: "multiple dirs", - skipDirs: []string{"/etc/*/*", "/var/log/*"}, + name: "multiple dirs", + skipDirs: []string{ + "/etc/*/*", + "/var/log/*", + }, wants: map[string]bool{ "/etc/foo": false, "/etc/foo/bar": true, @@ -139,7 +144,7 @@ func TestSkipDir(t *testing.T) { for dir, want := range tt.wants { dir = filepath.ToSlash(filepath.Clean(dir)) got := utils.SkipPath(dir, utils.CleanSkipPaths(tt.skipDirs)) - assert.Equal(t, want, got, fmt.Sprintf("defaultSkipDirs: %s, dir: %s", tt.skipDirs, dir)) + assert.Equal(t, want, got, "defaultSkipDirs: %s, dir: %s", tt.skipDirs, dir) } }) } diff --git a/pkg/plugin/index.go b/pkg/plugin/index.go index 57c6f0260877..82e4cb076356 100644 --- a/pkg/plugin/index.go +++ b/pkg/plugin/index.go @@ -61,7 +61,7 @@ func (m *Manager) Search(ctx context.Context, keyword string) error { } } - if _, err = fmt.Fprintf(m.w, buf.String()); err != nil { + if _, err = fmt.Fprint(m.w, buf.String()); err != nil { return err } From a9b557d9ddb863cee4bb60130f62521875356796 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 10:11:06 +0400 Subject: [PATCH 84/94] chore(deps): bump the github-actions group across 1 directory with 2 updates (#7854) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/reusable-release.yaml | 2 +- .github/workflows/test.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable-release.yaml b/.github/workflows/reusable-release.yaml index 0f7064ee18e1..54fa746f768f 100644 --- a/.github/workflows/reusable-release.yaml +++ b/.github/workflows/reusable-release.yaml @@ -28,7 +28,7 @@ jobs: contents: read # Not required for public repositories, but for clarity steps: - name: Cosign install - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 + uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index c2af5eb66bbb..1113a6a3a894 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -40,7 +40,7 @@ jobs: - name: Lint id: lint - uses: golangci/golangci-lint-action@v6.0.1 + uses: golangci/golangci-lint-action@v6.1.1 with: version: v1.61 args: --verbose --out-format=line-number From a6a45b346aede67af44e96c7b2b9abad1826890c Mon Sep 17 00:00:00 2001 From: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:14:05 +0600 Subject: [PATCH 85/94] test: save `containerd` image into archive and use in tests (#7816) --- .github/workflows/cache-test-images.yaml | 4 +- .github/workflows/test.yaml | 6 +- magefiles/fixture.go | 55 +++++++++++++------ pkg/fanal/test/integration/containerd_test.go | 7 ++- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/.github/workflows/cache-test-images.yaml b/.github/workflows/cache-test-images.yaml index 4b73cc2fb5bc..dd3a76d10638 100644 --- a/.github/workflows/cache-test-images.yaml +++ b/.github/workflows/cache-test-images.yaml @@ -29,7 +29,7 @@ jobs: run: | source integration/testimages.ini IMAGE_LIST=$(skopeo list-tags docker://$TEST_IMAGES) - DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) + DIGEST=$(echo "$IMAGE_LIST" | jq '.Tags += ["containerd"] | .Tags | sort' | sha256sum | cut -d' ' -f1) echo "digest=$DIGEST" >> $GITHUB_OUTPUT ## We need to work with test image cache only for main branch @@ -70,7 +70,7 @@ jobs: run: | source integration/testimages.ini IMAGE_LIST=$(skopeo list-tags docker://$TEST_VM_IMAGES) - DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) + DIGEST=$(echo "$IMAGE_LIST" | jq '.Tags | sort' | sha256sum | cut -d' ' -f1) echo "digest=$DIGEST" >> $GITHUB_OUTPUT ## We need to work with test VM image cache only for main branch diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 1113a6a3a894..9c6c2f10ffba 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -93,7 +93,7 @@ jobs: run: | source integration/testimages.ini IMAGE_LIST=$(skopeo list-tags docker://$TEST_IMAGES) - DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) + DIGEST=$(echo "$IMAGE_LIST" | jq '.Tags += ["containerd"] | .Tags | sort' | sha256sum | cut -d' ' -f1) echo "digest=$DIGEST" >> $GITHUB_OUTPUT - name: Restore test images from cache @@ -151,7 +151,7 @@ jobs: run: | source integration/testimages.ini IMAGE_LIST=$(skopeo list-tags docker://$TEST_IMAGES) - DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) + DIGEST=$(echo "$IMAGE_LIST" | jq '.Tags += ["containerd"] | .Tags | sort' | sha256sum | cut -d' ' -f1) echo "digest=$DIGEST" >> $GITHUB_OUTPUT - name: Restore test images from cache @@ -190,7 +190,7 @@ jobs: run: | source integration/testimages.ini IMAGE_LIST=$(skopeo list-tags docker://$TEST_VM_IMAGES) - DIGEST=$(echo "$IMAGE_LIST" | sha256sum | cut -d' ' -f1) + DIGEST=$(echo "$IMAGE_LIST" | jq '.Tags | sort' | sha256sum | cut -d' ' -f1) echo "digest=$DIGEST" >> $GITHUB_OUTPUT - name: Restore test VM images from cache diff --git a/magefiles/fixture.go b/magefiles/fixture.go index 0112a8421133..e7a2c395157e 100644 --- a/magefiles/fixture.go +++ b/magefiles/fixture.go @@ -14,9 +14,11 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" ) +const dir = "integration/testdata/fixtures/images/" + func fixtureContainerImages() error { var testImages = testutil.ImageName("", "", "") - const dir = "integration/testdata/fixtures/images/" + if err := os.MkdirAll(dir, 0750); err != nil { return err } @@ -24,26 +26,45 @@ func fixtureContainerImages() error { if err != nil { return err } + // Save all tags for trivy-test-images for _, tag := range tags { - fileName := tag + ".tar.gz" - filePath := filepath.Join(dir, fileName) - if exists(filePath) { - continue - } - fmt.Printf("Downloading %s...\n", tag) - imgName := fmt.Sprintf("%s:%s", testImages, tag) - img, err := crane.Pull(imgName) - if err != nil { - return err - } - tarPath := strings.TrimSuffix(filePath, ".gz") - if err = crane.Save(img, imgName, tarPath); err != nil { - return err - } - if err = sh.Run("gzip", tarPath); err != nil { + if err := saveImage("", tag); err != nil { return err } } + + // Save trivy-test-images/containerd image + if err := saveImage("containerd", "latest"); err != nil { + return err + } + return nil +} + +func saveImage(subpath, tag string) error { + fileName := tag + ".tar.gz" + imgName := testutil.ImageName("", tag, "") + if subpath != "" { + fileName = subpath + ".tar.gz" + imgName = testutil.ImageName(subpath, "", "") + } + filePath := filepath.Join(dir, fileName) + if exists(filePath) { + return nil + } + fmt.Printf("Downloading %s...\n", imgName) + + img, err := crane.Pull(imgName) + if err != nil { + return err + } + tarPath := strings.TrimSuffix(filePath, ".gz") + if err = crane.Save(img, imgName, tarPath); err != nil { + return err + } + if err = sh.Run("gzip", tarPath); err != nil { + return err + } + return nil } diff --git a/pkg/fanal/test/integration/containerd_test.go b/pkg/fanal/test/integration/containerd_test.go index 568af60528ea..420949cd42d3 100644 --- a/pkg/fanal/test/integration/containerd_test.go +++ b/pkg/fanal/test/integration/containerd_test.go @@ -76,9 +76,14 @@ func setupContainerd(t *testing.T, ctx context.Context, namespace string) *conta func startContainerd(t *testing.T, ctx context.Context, hostPath string) { t.Helper() t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true") + + // Load `containerd` image from tar file to avoid fetching it from remote registry + cli := testutil.NewDockerClient(t) + loadedImage := cli.ImageLoad(t, ctx, "../../../../integration/testdata/fixtures/images/containerd.tar.gz") + req := testcontainers.ContainerRequest{ Name: "containerd", - Image: testutil.ImageName("containerd", "latest", ""), + Image: loadedImage, Entrypoint: []string{ "/bin/sh", "-c", From 2529b58d4db8e73af977bbb601f966d9821c2367 Mon Sep 17 00:00:00 2001 From: Yeates Date: Tue, 5 Nov 2024 13:39:47 +0800 Subject: [PATCH 86/94] refactor(secret): optimize performance by moving ToLower operation outside loop (#7862) --- pkg/fanal/secret/scanner.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/fanal/secret/scanner.go b/pkg/fanal/secret/scanner.go index 33a3806f41b4..01283ea42a46 100644 --- a/pkg/fanal/secret/scanner.go +++ b/pkg/fanal/secret/scanner.go @@ -175,9 +175,9 @@ func (r *Rule) MatchKeywords(content []byte) bool { if len(r.Keywords) == 0 { return true } - + var contentLower = bytes.ToLower(content) for _, kw := range r.Keywords { - if bytes.Contains(bytes.ToLower(content), []byte(strings.ToLower(kw))) { + if bytes.Contains(contentLower, []byte(strings.ToLower(kw))) { return true } } From ed2288f1e7b1195db179191e51a1952272c2c064 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:40:34 +0000 Subject: [PATCH 87/94] chore(deps): bump github.com/golang-jwt/jwt/v4 from 4.5.0 to 4.5.1 (#7868) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index f4a034a8063a..fced18a28f4d 100644 --- a/go.mod +++ b/go.mod @@ -247,7 +247,7 @@ require ( github.com/goccy/go-yaml v1.9.5 // indirect github.com/gofrs/uuid v4.3.1+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect diff --git a/go.sum b/go.sum index 5eadfbf83818..f116a5db3505 100644 --- a/go.sum +++ b/go.sum @@ -710,8 +710,9 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= From b1c7f5516fc39c6cbb76cbeae5c8677ccc9ce5dd Mon Sep 17 00:00:00 2001 From: afdesk Date: Wed, 6 Nov 2024 04:58:01 +0600 Subject: [PATCH 88/94] feat(k8s): add default commands for unknown platform (#7863) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fced18a28f4d..c7bb5f608c47 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/aquasecurity/trivy-checks v1.2.2 github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1 github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 - github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241029051843-2606b7e0f0b4 + github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241101182546-89bffc3932bc github.com/aws/aws-sdk-go-v2 v1.31.0 github.com/aws/aws-sdk-go-v2/config v1.27.38 github.com/aws/aws-sdk-go-v2/credentials v1.17.36 diff --git a/go.sum b/go.sum index f116a5db3505..991cad7e2929 100644 --- a/go.sum +++ b/go.sum @@ -355,8 +355,8 @@ github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1 h1:G0gnacAOR github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1/go.mod h1:PYkSRx4dlgFATEt+okGwibvbxVEtqsOdH+vX/saACYE= github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 h1:JVgBIuIYbwG+ekC5lUHUpGJboPYiCcxiz06RCtz8neI= github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48/go.mod h1:Ldya37FLi0e/5Cjq2T5Bty7cFkzUDwTcPeQua+2M8i8= -github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241029051843-2606b7e0f0b4 h1:i0Z0JS4xtMAcBVOpYSciS7slmIBi1SmjT6garbrJtcA= -github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241029051843-2606b7e0f0b4/go.mod h1:ctlibFXOQyjWybeVVQI6NLG6GJoPWZJ4cIirQ/wPCQs= +github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241101182546-89bffc3932bc h1:/mFBYIK9RY+L8s1CIbQbJ5B3v0YmoDSu5eAzavvMa+Y= +github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241101182546-89bffc3932bc/go.mod h1:ctlibFXOQyjWybeVVQI6NLG6GJoPWZJ4cIirQ/wPCQs= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= From eda4d7660d8908705bc08a6edc55d8144d02806a Mon Sep 17 00:00:00 2001 From: Ben Foster Date: Wed, 6 Nov 2024 01:31:23 -0500 Subject: [PATCH 89/94] fix: Improve version comparisons when build identifiers are present (#7873) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c7bb5f608c47..93acd5cf9334 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798 github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 - github.com/aquasecurity/go-version v0.0.0-20240603093900-cf8a8d29271d + github.com/aquasecurity/go-version v0.0.0-20241105054539-1951e80d786f github.com/aquasecurity/table v1.8.0 github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8 github.com/aquasecurity/tml v0.6.1 diff --git a/go.sum b/go.sum index 991cad7e2929..f2112b2721ef 100644 --- a/go.sum +++ b/go.sum @@ -341,8 +341,8 @@ github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 h1: github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46/go.mod h1:olhPNdiiAAMiSujemd1O/sc6GcyePr23f/6uGKtthNg= github.com/aquasecurity/go-version v0.0.0-20201107203531-5e48ac5d022a/go.mod h1:9Beu8XsUNNfzml7WBf3QmyPToP1wm1Gj/Vc5UJKqTzU= github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492/go.mod h1:9Beu8XsUNNfzml7WBf3QmyPToP1wm1Gj/Vc5UJKqTzU= -github.com/aquasecurity/go-version v0.0.0-20240603093900-cf8a8d29271d h1:4zour5Sh9chOg+IqIinIcJ3qtr3cIf8FdFY6aArlXBw= -github.com/aquasecurity/go-version v0.0.0-20240603093900-cf8a8d29271d/go.mod h1:1cPOp4BaQZ1G2F5fnw4dFz6pkOyXJI9KTuak8ghIl3U= +github.com/aquasecurity/go-version v0.0.0-20241105054539-1951e80d786f h1:6mwfszC0VohA3NF75EX8pPStmmL0spZnTlkLp83M69c= +github.com/aquasecurity/go-version v0.0.0-20241105054539-1951e80d786f/go.mod h1:1cPOp4BaQZ1G2F5fnw4dFz6pkOyXJI9KTuak8ghIl3U= github.com/aquasecurity/table v1.8.0 h1:9ntpSwrUfjrM6/YviArlx/ZBGd6ix8W+MtojQcM7tv0= github.com/aquasecurity/table v1.8.0/go.mod h1:eqOmvjjB7AhXFgFqpJUEE/ietg7RrMSJZXyTN8E/wZw= github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8 h1:b43UVqYjz7qDqK+cVOtF2Lk6CxjytYItP6Pgf3wGsNE= From 6e3252b1d314ddcb4904e6f98abb8ac1e3d3cc94 Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Wed, 6 Nov 2024 11:32:43 +0400 Subject: [PATCH 90/94] chore: bump containerd to v2.0.0 (#7875) Signed-off-by: knqyf263 --- go.mod | 78 ++++---- go.sum | 180 ++++++++++-------- pkg/fanal/image/daemon/containerd.go | 56 +++--- pkg/fanal/test/integration/containerd_test.go | 19 +- 4 files changed, 180 insertions(+), 153 deletions(-) diff --git a/go.mod b/go.mod index 93acd5cf9334..566d5069c0b9 100644 --- a/go.mod +++ b/go.mod @@ -41,8 +41,10 @@ require ( github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/cenkalti/backoff/v4 v4.3.0 github.com/cheggaaa/pb/v3 v3.1.5 - github.com/containerd/containerd v1.7.22 + github.com/containerd/containerd/v2 v2.0.0 + github.com/containerd/platforms v1.0.0-rc.0 github.com/csaf-poc/csaf_distribution/v3 v3.0.0 + github.com/distribution/reference v0.6.0 github.com/docker/cli v27.2.1+incompatible github.com/docker/docker v27.3.1+incompatible github.com/docker/go-connections v0.5.0 @@ -119,16 +121,16 @@ require ( github.com/zclconf/go-cty v1.15.0 github.com/zclconf/go-cty-yaml v1.0.3 go.etcd.io/bbolt v1.3.11 - golang.org/x/crypto v0.27.0 - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/crypto v0.28.0 + golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect golang.org/x/mod v0.21.0 - golang.org/x/net v0.29.0 + golang.org/x/net v0.30.0 golang.org/x/sync v0.8.0 golang.org/x/term v0.25.0 - golang.org/x/text v0.18.0 + golang.org/x/text v0.19.0 golang.org/x/vuln v1.1.3 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 - google.golang.org/protobuf v1.34.2 + google.golang.org/protobuf v1.35.1 gopkg.in/yaml.v3 v3.0.1 helm.sh/helm/v3 v3.16.1 k8s.io/api v0.31.2 @@ -139,12 +141,12 @@ require ( require ( cloud.google.com/go v0.112.1 // indirect - cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect cloud.google.com/go/iam v1.1.6 // indirect cloud.google.com/go/storage v1.39.1 // indirect dario.cat/mergo v1.0.1 // indirect - github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect - github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect + github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect + github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect @@ -162,7 +164,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.0 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/Microsoft/hcsshim v0.12.0 // indirect + github.com/Microsoft/hcsshim v0.12.9 // indirect github.com/OneOfOne/xxhash v1.2.8 // indirect github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect github.com/VividCortex/ewma v1.2.0 // indirect @@ -191,29 +193,29 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect github.com/cloudflare/circl v1.3.8 // indirect - github.com/containerd/cgroups/v3 v3.0.2 // indirect - github.com/containerd/containerd/api v1.7.19 // indirect - github.com/containerd/continuity v0.4.3 // indirect - github.com/containerd/errdefs v0.1.0 // indirect + github.com/containerd/cgroups/v3 v3.0.3 // indirect + github.com/containerd/containerd v1.7.23 // indirect + github.com/containerd/containerd/api v1.8.0 // indirect + github.com/containerd/continuity v0.4.4 // indirect + github.com/containerd/errdefs v1.0.0 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/log v0.1.0 // indirect - github.com/containerd/platforms v0.2.1 // indirect + github.com/containerd/plugin v1.0.0 // indirect github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect - github.com/containerd/ttrpc v1.2.5 // indirect - github.com/containerd/typeurl/v2 v2.2.0 // indirect + github.com/containerd/ttrpc v1.2.6 // indirect + github.com/containerd/typeurl/v2 v2.2.2 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 // indirect github.com/cyphar/filepath-securejoin v0.3.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect - github.com/distribution/reference v0.6.0 // indirect github.com/dlclark/regexp2 v1.4.0 // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect - github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect @@ -281,7 +283,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491 // indirect @@ -303,7 +305,7 @@ require ( github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/spdystream v0.4.0 // indirect github.com/moby/sys/mountinfo v0.7.2 // indirect - github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/signal v0.7.1 // indirect github.com/moby/sys/user v0.3.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect @@ -318,16 +320,17 @@ require ( github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opencontainers/runtime-spec v1.2.0 // indirect - github.com/opencontainers/selinux v1.11.0 // indirect + github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect + github.com/opencontainers/selinux v1.11.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/prometheus/client_golang v1.20.2 // indirect + github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -353,6 +356,7 @@ require ( github.com/spf13/afero v1.11.0 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect + github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tchap/go-patricia/v2 v2.3.1 // indirect github.com/theupdateframework/go-tuf v0.7.0 // indirect @@ -375,25 +379,25 @@ require ( github.com/yusufpapurcu/wmi v1.2.4 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/sdk v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect + go.opentelemetry.io/otel v1.31.0 // indirect + go.opentelemetry.io/otel/metric v1.31.0 // indirect + go.opentelemetry.io/otel/sdk v1.31.0 // indirect + go.opentelemetry.io/otel/trace v1.31.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 // indirect golang.org/x/time v0.6.0 // indirect golang.org/x/tools v0.24.0 // indirect google.golang.org/api v0.172.0 // indirect google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/grpc v1.66.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect + google.golang.org/grpc v1.67.1 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect @@ -403,7 +407,7 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/apiextensions-apiserver v0.31.0 // indirect k8s.io/apimachinery v0.31.2 // indirect - k8s.io/apiserver v0.31.0 // indirect + k8s.io/apiserver v0.31.2 // indirect k8s.io/cli-runtime v0.31.2 // indirect k8s.io/client-go v0.31.2 // indirect k8s.io/component-base v0.31.2 // indirect @@ -422,4 +426,6 @@ require ( sigs.k8s.io/kustomize/api v0.17.2 // indirect sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + tags.cncf.io/container-device-interface v0.8.0 // indirect + tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect ) diff --git a/go.sum b/go.sum index f2112b2721ef..7618669c665c 100644 --- a/go.sum +++ b/go.sum @@ -68,8 +68,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= @@ -193,10 +193,10 @@ dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 h1:dIScnXFlF784X79oi7MzVT6GWqr/W1uUt0pB5CsDs9M= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2/go.mod h1:gCLVsLfv1egrcZu+GoJATN5ts75F2s62ih/457eWzOw= github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d h1:zjqpY4C7H15HjRPEenkS4SAn3Jy2eRRjkjZbGR30TOg= github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d/go.mod h1:XNqJ7hv2kY++g8XEHREpi+JqZo3+0l+CH2egBVN4yqM= github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo/helper v0.2.0 h1:8+4G8JaejP8Xa6W46PzJEwisNgBXMvFcz78N6zG/ARw= @@ -266,8 +266,8 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/Microsoft/hcsshim v0.12.0 h1:rbICA+XZFwrBef2Odk++0LjFvClNCJGRK+fsrP254Ts= -github.com/Microsoft/hcsshim v0.12.0/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= +github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg= +github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -480,36 +480,43 @@ github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUo github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ= github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= -github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= -github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= -github.com/containerd/containerd v1.7.22 h1:nZuNnNRA6T6jB975rx2RRNqqH2k6ELYKDZfqTHqwyy0= -github.com/containerd/containerd v1.7.22/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= -github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA= -github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig= -github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= -github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= -github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= -github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= +github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= +github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= +github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ= +github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= +github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= +github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= +github.com/containerd/containerd/v2 v2.0.0 h1:qLDdFaAykQrIyLiqwQrNLLz95wiC36bAZVwioUwqShM= +github.com/containerd/containerd/v2 v2.0.0/go.mod h1:j25kDy9P48/ngb1sxWIFfK6GsnqOHoSqo1EpAod20VQ= +github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= +github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= -github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/containerd/platforms v1.0.0-rc.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yuuhsGLWaXAA= +github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= +github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= +github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU= github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk= -github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU= -github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= -github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= -github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= +github.com/containerd/ttrpc v1.2.6 h1:zG+Kn5EZ6MUYCS1t2Hmt2J4tMVaLSFEJVOraDQwNPC4= +github.com/containerd/ttrpc v1.2.6/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= +github.com/containerd/typeurl/v2 v2.2.2 h1:3jN/k2ysKuPCsln5Qv8bzR9cxal8XjkxPogJfSNO31k= +github.com/containerd/typeurl/v2 v2.2.2/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU= github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0= github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/csaf-poc/csaf_distribution/v3 v3.0.0 h1:ob9+Fmpff0YWgTP3dYaw7G2hKQ9cegh9l3zksc+q3sM= @@ -638,8 +645,8 @@ github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= -github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= -github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -716,8 +723,8 @@ github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -866,8 +873,8 @@ github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJr github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -956,8 +963,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f h1:GvCU5GXhHq+7LeOzx/haG7HSIZokl3/0GkoUFzsRJjg= github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f/go.mod h1:q59u9px8b7UTj0nIjEjvmTWekazka6xIt6Uogz5Dm+8= @@ -1064,6 +1071,7 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs= github.com/moby/buildkit v0.16.0 h1:wOVBj1o5YNVad/txPQNXUXdelm7Hs/i0PUFjzbK0VKE= github.com/moby/buildkit v0.16.0/go.mod h1:Xqx/5GlrqE1yIRORk0NSCVDFpQAU1WjlT6KHYZdisIQ= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= @@ -1076,8 +1084,8 @@ github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8 github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= -github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= -github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0= github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8= github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= @@ -1099,6 +1107,7 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mozillazg/docker-credential-acr-helper v0.3.0 h1:DVWFZ3/O8BP6Ue3iS/Olw+G07u1hCq1EOVCDZZjCIBI= github.com/mozillazg/docker-credential-acr-helper v0.3.0/go.mod h1:cZlu3tof523ujmLuiNUb6JsjtHcNA70u1jitrrdnuyA= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -1135,10 +1144,14 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= -github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= +github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 h1:DmNGcqH3WDbV5k8OJ+esPWbqUOX5rMLR2PMvziDMJi0= +github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI= +github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8= +github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openvex/discovery v0.1.1-0.20240802171711-7c54efc57553 h1:c4u0GIH0w2Q57Pm2Oldrq6EiHFnLCCnRs98A+ggj/YQ= @@ -1154,8 +1167,8 @@ github.com/package-url/packageurl-go v0.1.3 h1:4juMED3hHiz0set3Vq3KeQ75KD1avthoX github.com/package-url/packageurl-go v0.1.3/go.mod h1:nKAWB8E6uk1MHqiS/lQb9pYBGH2+mdJ2PJc2s50dQY0= github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= @@ -1178,8 +1191,8 @@ github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjz github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg= -github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -1269,6 +1282,7 @@ github.com/sigstore/timestamp-authority v1.2.2 h1:X4qyutnCQqJ0apMewFyx+3t7Tws00J github.com/sigstore/timestamp-authority v1.2.2/go.mod h1:nEah4Eq4wpliDjlY342rXclGSO7Kb9hoRrl9tqLW13A= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= @@ -1317,6 +1331,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= @@ -1353,6 +1369,7 @@ github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4A github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= @@ -1422,24 +1439,24 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 h1:yMkBS9yViCc7U7yeLzJPM2XizlfdVvBRSmsQDWu6qc0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0/go.mod h1:n8MR6/liuGB5EmTETUBeU5ZgqMOlqKRxUaqPQBOANZ8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM= +go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= +go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= +go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= @@ -1466,8 +1483,8 @@ golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1478,8 +1495,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4= +golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1569,8 +1586,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1596,8 +1613,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1638,6 +1655,7 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1734,8 +1752,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1973,10 +1991,10 @@ google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 h1:ImUcDPHjTrAqNhlOkSocDLfG9rrNHH7w7uoKWPaWZ8s= google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7/go.mod h1:/3XmxOjePkvmKrHuBy4zNFw7IzxJXtAgdpXi8Ll990U= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg= +google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -2012,8 +2030,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= -google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2030,8 +2048,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2085,8 +2103,8 @@ k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24 k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/apiserver v0.31.0 h1:p+2dgJjy+bk+B1Csz+mc2wl5gHwvNkC9QJV+w55LVrY= -k8s.io/apiserver v0.31.0/go.mod h1:KI9ox5Yu902iBnnyMmy7ajonhKnkeZYJhTZ/YI+WEMk= +k8s.io/apiserver v0.31.2 h1:VUzOEUGRCDi6kX1OyQ801m4A7AUPglpsmGvdsekmcI4= +k8s.io/apiserver v0.31.2/go.mod h1:o3nKZR7lPlJqkU5I3Ove+Zx3JuoFjQobGX1Gctw6XuE= k8s.io/cli-runtime v0.31.2 h1:7FQt4C4Xnqx8V1GJqymInK0FFsoC+fAZtbLqgXYVOLQ= k8s.io/cli-runtime v0.31.2/go.mod h1:XROyicf+G7rQ6FQJMbeDV9jqxzkWXTYD6Uxd15noe0Q= k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= @@ -2148,3 +2166,7 @@ sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k= software.sslmate.com/src/go-pkcs12 v0.4.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI= +tags.cncf.io/container-device-interface v0.8.0 h1:8bCFo/g9WODjWx3m6EYl3GfUG31eKJbaggyBDxEldRc= +tags.cncf.io/container-device-interface v0.8.0/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y= +tags.cncf.io/container-device-interface/specs-go v0.8.0 h1:QYGFzGxvYK/ZLMrjhvY0RjpUavIn4KcmRmVP/JjdBTA= +tags.cncf.io/container-device-interface/specs-go v0.8.0/go.mod h1:BhJIkjjPh4qpys+qm4DAYtUyryaTDg9zris+AczXyws= diff --git a/pkg/fanal/image/daemon/containerd.go b/pkg/fanal/image/daemon/containerd.go index 109081d5bae5..faa5c8d98c3f 100644 --- a/pkg/fanal/image/daemon/containerd.go +++ b/pkg/fanal/image/daemon/containerd.go @@ -10,12 +10,12 @@ import ( "strings" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images/archive" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/platforms" - refdocker "github.com/containerd/containerd/reference/docker" + "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images/archive" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/platforms" + "github.com/distribution/reference" api "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/go-connections/nat" @@ -52,12 +52,12 @@ func (n familiarNamed) String() string { return string(n) } -func imageWriter(client *containerd.Client, img containerd.Image, platform types.Platform) imageSave { +func imageWriter(c *client.Client, img client.Image, platform types.Platform) imageSave { return func(ctx context.Context, ref []string) (io.ReadCloser, error) { if len(ref) < 1 { return nil, xerrors.New("no image reference") } - imgOpts := archive.WithImage(client.ImageService(), ref[0]) + imgOpts := archive.WithImage(c.ImageService(), ref[0]) manifestOpts := archive.WithManifest(img.Target()) var platformMatchComparer platforms.MatchComparer @@ -69,7 +69,7 @@ func imageWriter(client *containerd.Client, img containerd.Image, platform types platOpts := archive.WithPlatform(platformMatchComparer) pr, pw := io.Pipe() go func() { - pw.CloseWithError(archive.Export(ctx, client.ContentStore(), pw, imgOpts, manifestOpts, platOpts)) + pw.CloseWithError(archive.Export(ctx, c.ContentStore(), pw, imgOpts, manifestOpts, platOpts)) }() return pr, nil } @@ -94,17 +94,17 @@ func ContainerdImage(ctx context.Context, imageName string, opts types.ImageOpti return nil, cleanup, err } - var options []containerd.ClientOpt + var options []client.Opt if opts.RegistryOptions.Platform.Platform != nil { ociPlatform, err := platforms.Parse(opts.RegistryOptions.Platform.String()) if err != nil { return nil, cleanup, err } - options = append(options, containerd.WithDefaultPlatform(platforms.OnlyStrict(ociPlatform))) + options = append(options, client.WithDefaultPlatform(platforms.OnlyStrict(ociPlatform))) } - client, err := containerd.New(addr, options...) + c, err := client.New(addr, options...) if err != nil { return nil, cleanup, xerrors.Errorf("failed to initialize a containerd client: %w", err) } @@ -116,7 +116,7 @@ func ContainerdImage(ctx context.Context, imageName string, opts types.ImageOpti ctx = namespaces.WithNamespace(ctx, namespace) - imgs, err := client.ListImages(ctx, searchFilters...) + imgs, err := c.ListImages(ctx, searchFilters...) if err != nil { return nil, cleanup, xerrors.Errorf("failed to list images from containerd client: %w", err) } @@ -133,7 +133,7 @@ func ContainerdImage(ctx context.Context, imageName string, opts types.ImageOpti } cleanup = func() { - _ = client.Close() + _ = c.Close() _ = f.Close() _ = os.Remove(f.Name()) } @@ -144,21 +144,21 @@ func ContainerdImage(ctx context.Context, imageName string, opts types.ImageOpti } return &image{ - opener: imageOpener(ctx, ref.String(), f, imageWriter(client, img, opts.RegistryOptions.Platform)), + opener: imageOpener(ctx, ref.String(), f, imageWriter(c, img, opts.RegistryOptions.Platform)), inspect: insp, history: history, }, cleanup, nil } -func parseReference(imageName string) (refdocker.Reference, []string, error) { - ref, err := refdocker.ParseAnyReference(imageName) +func parseReference(imageName string) (reference.Reference, []string, error) { + ref, err := reference.ParseAnyReference(imageName) if err != nil { return nil, nil, xerrors.Errorf("parse error: %w", err) } - d, isDigested := ref.(refdocker.Digested) - n, isNamed := ref.(refdocker.Named) - nt, isNamedAndTagged := ref.(refdocker.NamedTagged) + d, isDigested := ref.(reference.Digested) + n, isNamed := ref.(reference.Named) + nt, isNamedAndTagged := ref.(reference.NamedTagged) // a name plus a digest // example: name@sha256:41adb3ef... @@ -168,7 +168,7 @@ func parseReference(imageName string) (refdocker.Reference, []string, error) { // comma-separated filter is logically anded return ref, []string{ fmt.Sprintf(`name~="^%s(:|@).*",target.digest==%q`, n.Name(), dgst), - fmt.Sprintf(`name~="^%s(:|@).*",target.digest==%q`, refdocker.FamiliarName(n), dgst), + fmt.Sprintf(`name~="^%s(:|@).*",target.digest==%q`, reference.FamiliarName(n), dgst), }, nil } @@ -184,7 +184,7 @@ func parseReference(imageName string) (refdocker.Reference, []string, error) { tag := nt.Tag() return familiarNamed(imageName), []string{ fmt.Sprintf(`name=="%s:%s"`, nt.Name(), tag), - fmt.Sprintf(`name=="%s:%s"`, refdocker.FamiliarName(nt), tag), + fmt.Sprintf(`name=="%s:%s"`, reference.FamiliarName(nt), tag), }, nil } @@ -193,7 +193,7 @@ func parseReference(imageName string) (refdocker.Reference, []string, error) { // readImageConfig reads the config spec (`application/vnd.oci.image.config.v1+json`) for img.platform from content store. // ported from https://github.com/containerd/nerdctl/blob/7dfbaa2122628921febeb097e7a8a86074dc931d/pkg/imgutil/imgutil.go#L377-L393 -func readImageConfig(ctx context.Context, img containerd.Image) (ocispec.Image, ocispec.Descriptor, error) { +func readImageConfig(ctx context.Context, img client.Image) (ocispec.Image, ocispec.Descriptor, error) { var config ocispec.Image configDesc, err := img.Config(ctx) // aware of img.platform @@ -211,19 +211,19 @@ func readImageConfig(ctx context.Context, img containerd.Image) (ocispec.Image, } // ported from https://github.com/containerd/nerdctl/blob/d110fea18018f13c3f798fa6565e482f3ff03591/pkg/inspecttypes/dockercompat/dockercompat.go#L279-L321 -func inspect(ctx context.Context, img containerd.Image, ref refdocker.Reference) (api.ImageInspect, []v1.History, refdocker.Reference, error) { - if _, ok := ref.(refdocker.Digested); ok { +func inspect(ctx context.Context, img client.Image, ref reference.Reference) (api.ImageInspect, []v1.History, reference.Reference, error) { + if _, ok := ref.(reference.Digested); ok { ref = familiarNamed(img.Name()) } var tag string - if tagged, ok := ref.(refdocker.Tagged); ok { + if tagged, ok := ref.(reference.Tagged); ok { tag = tagged.Tag() } var repository string - if n, isNamed := ref.(refdocker.Named); isNamed { - repository = refdocker.FamiliarName(n) + if n, isNamed := ref.(reference.Named); isNamed { + repository = reference.FamiliarName(n) } imgConfig, imgConfigDesc, err := readImageConfig(ctx, img) diff --git a/pkg/fanal/test/integration/containerd_test.go b/pkg/fanal/test/integration/containerd_test.go index 420949cd42d3..b635c3913d9c 100644 --- a/pkg/fanal/test/integration/containerd_test.go +++ b/pkg/fanal/test/integration/containerd_test.go @@ -15,13 +15,12 @@ import ( "testing" "time" - "github.com/samber/lo" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/namespaces" dockercontainer "github.com/docker/docker/api/types/container" v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/samber/lo" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" @@ -37,7 +36,7 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/types" ) -func setupContainerd(t *testing.T, ctx context.Context, namespace string) *containerd.Client { +func setupContainerd(t *testing.T, ctx context.Context, namespace string) *client.Client { t.Helper() tmpDir := t.TempDir() @@ -54,9 +53,9 @@ func setupContainerd(t *testing.T, ctx context.Context, namespace string) *conta startContainerd(t, ctx, tmpDir) // Retry up to 3 times until containerd is ready - var client *containerd.Client + var c *client.Client iteration, _, err := lo.AttemptWhileWithDelay(3, 1*time.Second, func(int, time.Duration) (error, bool) { - client, err = containerd.New(socketPath) + c, err = client.New(socketPath) if err != nil { if !errors.Is(err, os.ErrPermission) { return err, false // unexpected error @@ -64,13 +63,13 @@ func setupContainerd(t *testing.T, ctx context.Context, namespace string) *conta return err, true } t.Cleanup(func() { - require.NoError(t, client.Close()) + require.NoError(t, c.Close()) }) return nil, false }) require.NoErrorf(t, err, "attempted %d times ", iteration) - return client + return c } func startContainerd(t *testing.T, ctx context.Context, hostPath string) { From 601846134cb820c3e78324a44c7f0332d01b9fc6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2024 13:25:40 +0400 Subject: [PATCH 91/94] chore(deps): bump the common group across 1 directory with 20 updates (#7876) Signed-off-by: dependabot[bot] Signed-off-by: knqyf263 Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: knqyf263 --- go.mod | 71 ++++---- go.sum | 154 ++++++++++-------- integration/client_server_test.go | 2 +- integration/registry_test.go | 4 +- pkg/fanal/test/integration/containerd_test.go | 5 +- pkg/fanal/test/integration/registry_test.go | 2 +- 6 files changed, 123 insertions(+), 115 deletions(-) diff --git a/go.mod b/go.mod index 566d5069c0b9..c981c884a350 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,8 @@ toolchain go1.22.4 require ( github.com/Azure/azure-sdk-for-go v68.0.0+incompatible - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 github.com/BurntSushi/toml v1.4.0 github.com/CycloneDX/cyclonedx-go v0.9.1 github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible @@ -15,7 +15,7 @@ require ( github.com/NYTimes/gziphandler v1.1.1 github.com/alecthomas/chroma v0.10.0 github.com/alicebob/miniredis/v2 v2.33.0 - github.com/antchfx/htmlquery v1.3.2 + github.com/antchfx/htmlquery v1.3.3 github.com/apparentlymart/go-cidr v1.1.0 github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce @@ -29,26 +29,26 @@ require ( github.com/aquasecurity/trivy-db v0.0.0-20240910133327-7e0f4d2ed4c1 github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20241101182546-89bffc3932bc - github.com/aws/aws-sdk-go-v2 v1.31.0 - github.com/aws/aws-sdk-go-v2/config v1.27.38 - github.com/aws/aws-sdk-go-v2/credentials v1.17.36 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.179.1 - github.com/aws/aws-sdk-go-v2/service/ecr v1.35.2 - github.com/aws/aws-sdk-go-v2/service/s3 v1.63.2 - github.com/aws/aws-sdk-go-v2/service/sts v1.31.2 // indirect - github.com/aws/smithy-go v1.21.0 + github.com/aws/aws-sdk-go-v2 v1.32.3 + github.com/aws/aws-sdk-go-v2/config v1.28.1 + github.com/aws/aws-sdk-go-v2/credentials v1.17.42 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.187.0 + github.com/aws/aws-sdk-go-v2/service/ecr v1.36.3 + github.com/aws/aws-sdk-go-v2/service/s3 v1.66.2 + github.com/aws/aws-sdk-go-v2/service/sts v1.32.3 // indirect + github.com/aws/smithy-go v1.22.0 github.com/bitnami/go-version v0.0.0-20231130084017-bb00604d650c - github.com/bmatcuk/doublestar/v4 v4.6.1 + github.com/bmatcuk/doublestar/v4 v4.7.1 github.com/cenkalti/backoff/v4 v4.3.0 github.com/cheggaaa/pb/v3 v3.1.5 github.com/containerd/containerd/v2 v2.0.0 github.com/containerd/platforms v1.0.0-rc.0 github.com/csaf-poc/csaf_distribution/v3 v3.0.0 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.2.1+incompatible + github.com/docker/cli v27.3.1+incompatible github.com/docker/docker v27.3.1+incompatible github.com/docker/go-connections v0.5.0 - github.com/fatih/color v1.17.0 + github.com/fatih/color v1.18.0 github.com/go-git/go-git/v5 v5.12.0 github.com/go-openapi/runtime v0.28.0 // indirect github.com/go-openapi/strfmt v0.23.0 // indirect @@ -90,8 +90,8 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/mitchellh/mapstructure v1.5.0 - github.com/moby/buildkit v0.16.0 - github.com/open-policy-agent/opa v0.68.1-0.20240903211041-76f7038ea2d1 + github.com/moby/buildkit v0.17.0 + github.com/open-policy-agent/opa v0.70.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0 github.com/openvex/discovery v0.1.1-0.20240802171711-7c54efc57553 @@ -112,17 +112,17 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 - github.com/testcontainers/testcontainers-go/modules/localstack v0.33.0 - github.com/tetratelabs/wazero v1.8.0 + github.com/testcontainers/testcontainers-go v0.34.0 + github.com/testcontainers/testcontainers-go/modules/localstack v0.34.0 + github.com/tetratelabs/wazero v1.8.1 github.com/twitchtv/twirp v8.1.3+incompatible github.com/xeipuuv/gojsonschema v1.2.0 github.com/xlab/treeprint v1.2.0 github.com/zclconf/go-cty v1.15.0 - github.com/zclconf/go-cty-yaml v1.0.3 + github.com/zclconf/go-cty-yaml v1.1.0 go.etcd.io/bbolt v1.3.11 golang.org/x/crypto v0.28.0 - golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect + golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/mod v0.21.0 golang.org/x/net v0.30.0 golang.org/x/sync v0.8.0 @@ -132,7 +132,7 @@ require ( golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 google.golang.org/protobuf v1.35.1 gopkg.in/yaml.v3 v3.0.1 - helm.sh/helm/v3 v3.16.1 + helm.sh/helm/v3 v3.16.2 k8s.io/api v0.31.2 k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 modernc.org/sqlite v1.33.1 @@ -169,22 +169,22 @@ require ( github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect github.com/VividCortex/ewma v1.2.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect - github.com/agnivade/levenshtein v1.1.1 // indirect + github.com/agnivade/levenshtein v1.2.0 // indirect github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect - github.com/antchfx/xpath v1.3.1 // indirect + github.com/antchfx/xpath v1.3.2 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go v1.55.5 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.23.2 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.3 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/blang/semver v3.5.1+incompatible // indirect @@ -205,7 +205,7 @@ require ( github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect github.com/containerd/ttrpc v1.2.6 // indirect github.com/containerd/typeurl/v2 v2.2.2 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 // indirect github.com/cyphar/filepath-securejoin v0.3.1 // indirect @@ -328,6 +328,7 @@ require ( github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/prometheus/client_golang v1.20.5 // indirect @@ -391,8 +392,8 @@ require ( golang.org/x/oauth2 v0.22.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 // indirect - golang.org/x/time v0.6.0 // indirect - golang.org/x/tools v0.24.0 // indirect + golang.org/x/time v0.7.0 // indirect + golang.org/x/tools v0.25.0 // indirect google.golang.org/api v0.172.0 // indirect google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect @@ -405,7 +406,7 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/apiextensions-apiserver v0.31.0 // indirect + k8s.io/apiextensions-apiserver v0.31.1 // indirect k8s.io/apimachinery v0.31.2 // indirect k8s.io/apiserver v0.31.2 // indirect k8s.io/cli-runtime v0.31.2 // indirect diff --git a/go.sum b/go.sum index 7618669c665c..8df679b57a6b 100644 --- a/go.sum +++ b/go.sum @@ -203,10 +203,12 @@ github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo/helper v0.2.0/go.mod h1:GgeIE+1be8Ivm7Sh4RgwI42aTtC9qrcj+Y9Y6CjJhJs= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0 h1:+m0M/LFxN43KvULkDNfdXOgrjtg6UYJPFBJyuEcRCAw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0/go.mod h1:PwOyop78lveYMRs6oCxjiVyBdyCgIYH6XHIVZO9/SFQ= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 h1:DRiANoJTiW6obBQe3SqZizkuV1PEgfiiGivmVocDy64= @@ -235,6 +237,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -283,8 +287,8 @@ github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1o github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= -github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY= +github.com/agnivade/levenshtein v1.2.0/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -321,10 +325,10 @@ github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1 github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/antchfx/htmlquery v1.3.2 h1:85YdttVkR1rAY+Oiv/nKI4FCimID+NXhDn82kz3mEvs= -github.com/antchfx/htmlquery v1.3.2/go.mod h1:1mbkcEgEarAokJiWhTfr4hR06w/q2ZZjnYLrDt6CTUk= -github.com/antchfx/xpath v1.3.1 h1:PNbFuUqHwWl0xRjvUPjJ95Agbmdj2uzzIwmQKgu4oCk= -github.com/antchfx/xpath v1.3.1/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= +github.com/antchfx/htmlquery v1.3.3 h1:x6tVzrRhVNfECDaVxnZi1mEGrQg3mjE/rxbH2Pe6dNE= +github.com/antchfx/htmlquery v1.3.3/go.mod h1:WeU3N7/rL6mb6dCwtE30dURBnBieKDC/fR8t6X+cKjU= +github.com/antchfx/xpath v1.3.2 h1:LNjzlsSjinu3bQpw9hWMY9ocB80oLOWuQqFvO6xt51U= +github.com/antchfx/xpath v1.3.2/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= @@ -366,44 +370,44 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:W github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/aws/aws-sdk-go-v2 v1.31.0 h1:3V05LbxTSItI5kUqNwhJrrrY1BAXxXt0sN0l72QmG5U= -github.com/aws/aws-sdk-go-v2 v1.31.0/go.mod h1:ztolYtaEUtdpf9Wftr31CJfLVjOnD/CVRkKOOYgF8hA= -github.com/aws/aws-sdk-go-v2/config v1.27.38 h1:mMVyJJuSUdbD4zKXoxDgWrgM60QwlFEg+JhihCq6wCw= -github.com/aws/aws-sdk-go-v2/config v1.27.38/go.mod h1:6xOiNEn58bj/64MPKx89r6G/el9JZn8pvVbquSqTKK4= -github.com/aws/aws-sdk-go-v2/credentials v1.17.36 h1:zwI5WrT+oWWfzSKoTNmSyeBKQhsFRJRv+PGW/UZW+Yk= -github.com/aws/aws-sdk-go-v2/credentials v1.17.36/go.mod h1:3AG/sY1rc9NJrNWcN/3KPU4SIDPGTrd/qegKB0TnFdE= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 h1:C/d03NAmh8C4BZXhuRNboF/DqhBkBCeDiJDcaqIT5pA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14/go.mod h1:7I0Ju7p9mCIdlrfS+JCgqcYD0VXz/N4yozsox+0o078= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 h1:kYQ3H1u0ANr9KEKlGs/jTLrBFPo8P8NaH/w7A01NeeM= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18/go.mod h1:r506HmK5JDUh9+Mw4CfGJGSSoqIiLCndAuqXuhbv67Y= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 h1:Z7IdFUONvTcvS7YuhtVxN99v2cCoHRXOS4mTr0B/pUc= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18/go.mod h1:DkKMmksZVVyat+Y+r1dEOgJEfUeA7UngIHWeKsi0yNc= +github.com/aws/aws-sdk-go-v2 v1.32.3 h1:T0dRlFBKcdaUPGNtkBSwHZxrtis8CQU17UpNBZYd0wk= +github.com/aws/aws-sdk-go-v2 v1.32.3/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= +github.com/aws/aws-sdk-go-v2/config v1.28.1 h1:oxIvOUXy8x0U3fR//0eq+RdCKimWI900+SV+10xsCBw= +github.com/aws/aws-sdk-go-v2/config v1.28.1/go.mod h1:bRQcttQJiARbd5JZxw6wG0yIK3eLeSCPdg6uqmmlIiI= +github.com/aws/aws-sdk-go-v2/credentials v1.17.42 h1:sBP0RPjBU4neGpIYyx8mkU2QqLPl5u9cmdTWVzIpHkM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.42/go.mod h1:FwZBfU530dJ26rv9saAbxa9Ej3eF/AK0OAY86k13n4M= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18 h1:68jFVtt3NulEzojFesM/WVarlFpCaXLKaBxDpzkQ9OQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18/go.mod h1:Fjnn5jQVIo6VyedMc0/EhPpfNlPl7dHV916O6B+49aE= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 h1:Jw50LwEkVjuVzE1NzkhNKkBf9cRN7MtE1F/b2cOKTUM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22/go.mod h1:Y/SmAyPcOTmpeVaWSzSKiILfXTVJwrGmYZhcRbhWuEY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 h1:981MHwBaRZM7+9QSR6XamDzF/o7ouUGxFzr+nVSIhrs= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22/go.mod h1:1RA1+aBEfn+CAB/Mh0MB6LsdCYCnjZm7tKXtnk499ZQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1 h1:SeDJWG4pmye+/aO6k+zt9clPTUy1MXqUmkW8rbAddQg= github.com/aws/aws-sdk-go-v2/service/ebs v1.22.1/go.mod h1:wRzaW0v9GGQS0h//wpsVDw3Hah5gs5UP+NxoyGeZIGM= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.179.1 h1:TwFjSwRn1kR1i1qeq5cQBRwRaZ80JQS8BHsJTb6QBk8= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.179.1/go.mod h1:W6sNzs5T4VpZn1Vy+FMKw8s24vt5k6zPJXcNOK0asBo= -github.com/aws/aws-sdk-go-v2/service/ecr v1.35.2 h1:bVNvja4oEB7v+VL1yP46hWthCPp+KYpZBLS2AifM5PY= -github.com/aws/aws-sdk-go-v2/service/ecr v1.35.2/go.mod h1:oRaGEExKI6Pqcow+Tt7wpJf73/Srcj/CUJv5Eb9QFhg= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.187.0 h1:cA4hWo269CN5RY7Arqt8BfzXF0KIN8DSNo/KcqHKkWk= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.187.0/go.mod h1:ossaD9Z1ugYb6sq9QIqQLEOorCGcqUoxlhud9M9yE70= +github.com/aws/aws-sdk-go-v2/service/ecr v1.36.3 h1:bqmoQEKpWFRDRxOv4lC5yZLc+N1cogZHPLeQACfVUJo= +github.com/aws/aws-sdk-go-v2/service/ecr v1.36.3/go.mod h1:KwOqlt4MOBK9EpOGkj8RU9fqfTEae5AOUHi1pDEZ3OQ= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.18.2 h1:PpbXaecV3sLAS6rjQiaKw4/jyq3Z8gNzmoJupHAoBp0= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.18.2/go.mod h1:fUHpGXr4DrXkEDpGAjClPsviWf+Bszeb0daKE0blxv8= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 h1:QFASJGfT8wMXtuP3D5CRmMjARHv9ZmzFUMJznHDOY3w= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5/go.mod h1:QdZ3OmoIjSX+8D1OPAzPxDfjXASbBMDsz9qvtyIhtik= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 h1:Xbwbmk44URTiHNx6PNo0ujDE6ERlsCKJD3u1zfnzAPg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20/go.mod h1:oAfOFzUB14ltPZj1rWwRc3d/6OgD76R8KlvU3EqM9Fg= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 h1:TToQNkvGguu209puTojY/ozlqy2d/SFNcoLIqTFi42g= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1:0jp+ltwkf+SwG2fm/PKo8t4y8pJSgOCO4D8Lz3k0aHQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 h1:qcxX0JYlgWH3hpPUnd6U0ikcl6LLA9sLkXE2w1fpMvY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3/go.mod h1:cLSNEmI45soc+Ef8K/L+8sEA3A3pYFEYf5B5UI+6bH4= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= -github.com/aws/aws-sdk-go-v2/service/s3 v1.63.2 h1:1iXmXy8SJzQVMGvo40TSzBYS9ig6BSyXfRIMzLfmBfE= -github.com/aws/aws-sdk-go-v2/service/s3 v1.63.2/go.mod h1:NLTqRLe3pUNu3nTEHI6XlHLKYmc8fbHUdMxAB6+s41Q= -github.com/aws/aws-sdk-go-v2/service/sso v1.23.2 h1:yzi/y/vKlLyzOfG7pSu5ONNGRxHIgLeDrV4w2AMRCo0= -github.com/aws/aws-sdk-go-v2/service/sso v1.23.2/go.mod h1:XRlMvmad0ZNL+75C5FYdMvbbLkd6qiqz6foR1nA1PXY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.2 h1:3gb6pYhYLjo8rB1h2Tqs61wpjRd3rQymYcVq/pp0yxI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.2/go.mod h1:FnvDM4sfa+isJ3kDXIzAB9GAwVSzFzSy97uZ3IsHo4E= -github.com/aws/aws-sdk-go-v2/service/sts v1.31.2 h1:O6tyji8mXmBGsHvTCB0VIhrDw19lGTUSbKIyjnw79s8= -github.com/aws/aws-sdk-go-v2/service/sts v1.31.2/go.mod h1:yMWe0F+XG0DkRZK5ODZhG7BEFYhLXi2dqGsv6tX0cgI= -github.com/aws/smithy-go v1.21.0 h1:H7L8dtDRk0P1Qm6y0ji7MCYMQObJ5R9CRpyPhRUkLYA= -github.com/aws/smithy-go v1.21.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aws/aws-sdk-go-v2/service/s3 v1.66.2 h1:p9TNFL8bFUMd+38YIpTAXpoxyz0MxC7FlbFEH4P4E1U= +github.com/aws/aws-sdk-go-v2/service/s3 v1.66.2/go.mod h1:fNjyo0Coen9QTwQLWeV6WO2Nytwiu+cCcWaTdKCAqqE= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.3 h1:UTpsIf0loCIWEbrqdLb+0RxnTXfWh2vhw4nQmFi4nPc= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.3/go.mod h1:FZ9j3PFHHAR+w0BSEjK955w5YD2UwB/l/H0yAK3MJvI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3 h1:2YCmIXv3tmiItw0LlYf6v7gEHebLY45kBEnPezbUKyU= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3/go.mod h1:u19stRyNPxGhj6dRm+Cdgu6N75qnbW7+QN0q0dsAk58= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.3 h1:wVnQ6tigGsRqSWDEEyH6lSAJ9OyFUsSnbaUWChuSGzs= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.3/go.mod h1:VZa9yTFyj4o10YGsmDO4gbQJUvvhY72fhumT8W4LqsE= +github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= +github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8 h1:SoFYaT9UyGkR0+nogNyD/Lj+bsixB+SNuAS4ABlEs6M= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8/go.mod h1:2JF49jcDOrLStIXN/j/K1EKRq8a8R2qRnlZA6/o/c7c= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -418,8 +422,8 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= -github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q= +github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A= @@ -511,8 +515,8 @@ github.com/containerd/typeurl/v2 v2.2.2/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsx github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU= github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= @@ -537,8 +541,8 @@ github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWa github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= -github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/digitorus/pkcs7 v0.0.0-20230713084857-e76b763bdc49/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc= github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 h1:ge14PCmCvPjpMQMIAH7uKg0lrtNSOdpYsRXlwk3QbaE= github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc= @@ -552,8 +556,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/docker/cli v27.2.1+incompatible h1:U5BPtiD0viUzjGAjV1p0MGB8eVA3L3cbIrnyWmSJI70= -github.com/docker/cli v27.2.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= +github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= @@ -600,8 +604,8 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= @@ -959,6 +963,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= @@ -1072,8 +1078,8 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs= -github.com/moby/buildkit v0.16.0 h1:wOVBj1o5YNVad/txPQNXUXdelm7Hs/i0PUFjzbK0VKE= -github.com/moby/buildkit v0.16.0/go.mod h1:Xqx/5GlrqE1yIRORk0NSCVDFpQAU1WjlT6KHYZdisIQ= +github.com/moby/buildkit v0.17.0 h1:ZA/4AxwBbve1f3ZaNNJQiCBtTV62R6YweWNwq4A+sTc= +github.com/moby/buildkit v0.17.0/go.mod h1:ru8NFyDHD8HbuKaLXJIjK9nr3x6FZR+IWjtF07S+wdM= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= @@ -1138,8 +1144,8 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= -github.com/open-policy-agent/opa v0.68.1-0.20240903211041-76f7038ea2d1 h1:GQrryTKpunLNDc2NdhNL1FzfrbuNvo45s76anGdqz9k= -github.com/open-policy-agent/opa v0.68.1-0.20240903211041-76f7038ea2d1/go.mod h1:5E5SvaPwTpwt2WM177I9Z3eT7qUpmOGjk1ZdHs+TZ4w= +github.com/open-policy-agent/opa v0.70.0 h1:B3cqCN2iQAyKxK6+GI+N40uqkin+wzIrM7YA60t9x1U= +github.com/open-policy-agent/opa v0.70.0/go.mod h1:Y/nm5NY0BX0BqjBriKUiV81sCl8XOjjvqQG7dXrggtI= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -1180,6 +1186,8 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjL github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1213,6 +1221,8 @@ github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= +github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -1339,12 +1349,12 @@ github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BG github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo= github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw= -github.com/testcontainers/testcontainers-go v0.33.0 h1:zJS9PfXYT5O0ZFXM2xxXfk4J5UMw/kRiISng037Gxdw= -github.com/testcontainers/testcontainers-go v0.33.0/go.mod h1:W80YpTa8D5C3Yy16icheD01UTDu+LmXIA2Keo+jWtT8= -github.com/testcontainers/testcontainers-go/modules/localstack v0.33.0 h1:AhbUGUjneEnMyTV5aTsPYzDiAWrba1duPtiV+Z9CKdY= -github.com/testcontainers/testcontainers-go/modules/localstack v0.33.0/go.mod h1:J5vMq1fXXiTfwcJplMClHhn+j8+MbIMv7Lic4d9E8qU= -github.com/tetratelabs/wazero v1.8.0 h1:iEKu0d4c2Pd+QSRieYbnQC9yiFlMS9D+Jr0LsRmcF4g= -github.com/tetratelabs/wazero v1.8.0/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= +github.com/testcontainers/testcontainers-go v0.34.0 h1:5fbgF0vIN5u+nD3IWabQwRybuB4GY8G2HHgCkbMzMHo= +github.com/testcontainers/testcontainers-go v0.34.0/go.mod h1:6P/kMkQe8yqPHfPWNulFGdFHTD8HB2vLq/231xY2iPQ= +github.com/testcontainers/testcontainers-go/modules/localstack v0.34.0 h1:WkjVmea0XQyGTY10Er8fOsVjHQ77iJCmTExnx6fC3Tw= +github.com/testcontainers/testcontainers-go/modules/localstack v0.34.0/go.mod h1:rTo76O/BBeAtfazMQqLvfwBrntBBwDP7/+Z60dm3e9U= +github.com/tetratelabs/wazero v1.8.1 h1:NrcgVbWfkWvVc4UtT4LRLDf91PsOzDzefMdwhLfA550= +github.com/tetratelabs/wazero v1.8.1/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg= github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU= github.com/theupdateframework/go-tuf v0.7.0 h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI= @@ -1421,8 +1431,8 @@ github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ github.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= -github.com/zclconf/go-cty-yaml v1.0.3 h1:og/eOQ7lvA/WWhHGFETVWNduJM7Rjsv2RRpx1sdFMLc= -github.com/zclconf/go-cty-yaml v1.0.3/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs= +github.com/zclconf/go-cty-yaml v1.1.0 h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0= +github.com/zclconf/go-cty-yaml v1.1.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs= github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs= github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= @@ -1495,8 +1505,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4= -golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1757,8 +1767,8 @@ golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1817,8 +1827,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= +golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= golang.org/x/vuln v1.1.3 h1:NPGnvPOTgnjBc9HTaUx+nj+EaUYxl5SJOWqaDYGaFYw= golang.org/x/vuln v1.1.3/go.mod h1:7Le6Fadm5FOqE9C926BCD0g12NWyhg7cxV4BwcPFuNY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2088,8 +2098,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -helm.sh/helm/v3 v3.16.1 h1:cER6tI/8PgUAsaJaQCVBUg3VI9KN4oVaZJgY60RIc0c= -helm.sh/helm/v3 v3.16.1/go.mod h1:r+xBHHP20qJeEqtvBXMf7W35QDJnzY/eiEBzt+TfHps= +helm.sh/helm/v3 v3.16.2 h1:Y9v7ry+ubQmi+cb5zw1Llx8OKHU9Hk9NQ/+P+LGBe2o= +helm.sh/helm/v3 v3.16.2/go.mod h1:SyTXgKBjNqi2NPsHCW5dDAsHqvGIu0kdNYNH9gQaw70= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2099,8 +2109,8 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= -k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= -k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= +k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40= +k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ= k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= k8s.io/apiserver v0.31.2 h1:VUzOEUGRCDi6kX1OyQ801m4A7AUPglpsmGvdsekmcI4= diff --git a/integration/client_server_test.go b/integration/client_server_test.go index 4afed3fdc155..0df09c6ae051 100644 --- a/integration/client_server_test.go +++ b/integration/client_server_test.go @@ -559,7 +559,7 @@ func TestClientServerWithRedis(t *testing.T) { }) // Terminate the Redis container - require.NoError(t, redisC.Terminate(ctx)) + require.NoError(t, testcontainers.TerminateContainer(redisC)) t.Run("sad path", func(t *testing.T) { osArgs := setupClient(t, testArgs, addr, cacheDir) diff --git a/integration/registry_test.go b/integration/registry_test.go index 25ddaf5b2814..3f0469e2c396 100644 --- a/integration/registry_test.go +++ b/integration/registry_test.go @@ -132,7 +132,7 @@ func TestRegistry(t *testing.T) { // set up auth server authC, err := setupAuthServer(ctx, baseDir) require.NoError(t, err) - defer authC.Terminate(ctx) + testcontainers.CleanupContainer(t, authC) authURL, err := getURL(ctx, authC, authPort) require.NoError(t, err) @@ -140,7 +140,7 @@ func TestRegistry(t *testing.T) { // set up registry registryC, err := setupRegistry(ctx, baseDir, authURL) require.NoError(t, err) - defer registryC.Terminate(ctx) + testcontainers.CleanupContainer(t, registryC) registryURL, err := getURL(ctx, registryC, registryPort) require.NoError(t, err) diff --git a/pkg/fanal/test/integration/containerd_test.go b/pkg/fanal/test/integration/containerd_test.go index b635c3913d9c..375c5cd77c62 100644 --- a/pkg/fanal/test/integration/containerd_test.go +++ b/pkg/fanal/test/integration/containerd_test.go @@ -101,6 +101,7 @@ func startContainerd(t *testing.T, ctx context.Context, hostPath string) { Started: true, }) require.NoError(t, err) + testcontainers.CleanupContainer(t, containerdC) _, _, err = containerdC.Exec(ctx, []string{ "chmod", @@ -108,10 +109,6 @@ func startContainerd(t *testing.T, ctx context.Context, hostPath string) { "/run/containerd/containerd.sock", }) require.NoError(t, err) - - t.Cleanup(func() { - require.NoError(t, containerdC.Terminate(ctx)) - }) } // Each of these tests imports an image and tags it with the name found in the diff --git a/pkg/fanal/test/integration/registry_test.go b/pkg/fanal/test/integration/registry_test.go index 4bca93f0ccba..35a32536600e 100644 --- a/pkg/fanal/test/integration/registry_test.go +++ b/pkg/fanal/test/integration/registry_test.go @@ -73,7 +73,7 @@ func TestTLSRegistry(t *testing.T) { Started: true, }) require.NoError(t, err) - defer registryC.Terminate(ctx) + testcontainers.CleanupContainer(t, registryC) registryURL, err := getRegistryURL(ctx, registryC, registryPort) require.NoError(t, err) From ab32297e0a8220a427fa330025f8625281e02275 Mon Sep 17 00:00:00 2001 From: Pierre Guilleminot Date: Thu, 7 Nov 2024 11:22:29 +0100 Subject: [PATCH 92/94] fix(fs): add missing defered Cleanup() call to post analyzer fs (#7882) --- pkg/fanal/artifact/local/fs.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/fanal/artifact/local/fs.go b/pkg/fanal/artifact/local/fs.go index 2f5ef7fe4ecd..b6c2d46c839a 100644 --- a/pkg/fanal/artifact/local/fs.go +++ b/pkg/fanal/artifact/local/fs.go @@ -82,6 +82,7 @@ func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) { if err != nil { return artifact.Reference{}, xerrors.Errorf("failed to prepare filesystem for post analysis: %w", err) } + defer composite.Cleanup() err = a.walker.Walk(a.rootPath, a.artifactOption.WalkerOption, func(filePath string, info os.FileInfo, opener analyzer.Opener) error { dir := a.rootPath From 99b2db3978562689cef956a71281abb84ff0ce47 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Fri, 8 Nov 2024 07:21:49 +0600 Subject: [PATCH 93/94] fix(misconf): handle null properties in CloudFormation templates (#7813) Signed-off-by: nikpivkin --- .../cloudformation/parser/file_context.go | 10 ++++ .../scanners/cloudformation/parser/parser.go | 33 +++++++------ .../cloudformation/parser/parser_test.go | 49 +++++++++++++++++++ 3 files changed, 77 insertions(+), 15 deletions(-) diff --git a/pkg/iac/scanners/cloudformation/parser/file_context.go b/pkg/iac/scanners/cloudformation/parser/file_context.go index 949add1ca7c4..e1c8cfa87f40 100644 --- a/pkg/iac/scanners/cloudformation/parser/file_context.go +++ b/pkg/iac/scanners/cloudformation/parser/file_context.go @@ -1,6 +1,8 @@ package parser import ( + "github.com/samber/lo" + "github.com/aquasecurity/trivy/pkg/iac/ignore" iacTypes "github.com/aquasecurity/trivy/pkg/iac/types" ) @@ -71,3 +73,11 @@ func (t *FileContext) missingParameterValues() []string { } return missing } + +func (t *FileContext) stripNullProperties() { + for _, resource := range t.Resources { + resource.Inner.Properties = lo.OmitBy(resource.Inner.Properties, func(k string, v *Property) bool { + return v.IsNil() + }) + } +} diff --git a/pkg/iac/scanners/cloudformation/parser/parser.go b/pkg/iac/scanners/cloudformation/parser/parser.go index 696dfcf16349..24d85ba4bbbb 100644 --- a/pkg/iac/scanners/cloudformation/parser/parser.go +++ b/pkg/iac/scanners/cloudformation/parser/parser.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "io/fs" + "path" "path/filepath" "strings" @@ -83,7 +84,7 @@ func (p *Parser) ParseFS(ctx context.Context, fsys fs.FS, dir string) (FileConte return contexts, nil } -func (p *Parser) ParseFile(ctx context.Context, fsys fs.FS, path string) (fctx *FileContext, err error) { +func (p *Parser) ParseFile(ctx context.Context, fsys fs.FS, filePath string) (fctx *FileContext, err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("panic during parse: %s", e) @@ -105,15 +106,15 @@ func (p *Parser) ParseFile(ctx context.Context, fsys fs.FS, path string) (fctx * } sourceFmt := YamlSourceFormat - if strings.HasSuffix(strings.ToLower(path), ".json") { + if path.Ext(filePath) == ".json" { sourceFmt = JsonSourceFormat } - f, err := fsys.Open(filepath.ToSlash(path)) + f, err := fsys.Open(filePath) if err != nil { return nil, err } - defer func() { _ = f.Close() }() + defer f.Close() content, err := io.ReadAll(f) if err != nil { @@ -123,7 +124,7 @@ func (p *Parser) ParseFile(ctx context.Context, fsys fs.FS, path string) (fctx * lines := strings.Split(string(content), "\n") fctx = &FileContext{ - filepath: path, + filepath: filePath, lines: lines, SourceFormat: sourceFmt, } @@ -131,26 +132,28 @@ func (p *Parser) ParseFile(ctx context.Context, fsys fs.FS, path string) (fctx * switch sourceFmt { case YamlSourceFormat: if err := yaml.Unmarshal(content, fctx); err != nil { - return nil, NewErrInvalidContent(path, err) + return nil, NewErrInvalidContent(filePath, err) } - fctx.Ignores = ignore.Parse(string(content), path, "") + fctx.Ignores = ignore.Parse(string(content), filePath, "") case JsonSourceFormat: if err := jfather.Unmarshal(content, fctx); err != nil { - return nil, NewErrInvalidContent(path, err) + return nil, NewErrInvalidContent(filePath, err) } } + fctx.stripNullProperties() + fctx.overrideParameters(p.overridedParameters) if params := fctx.missingParameterValues(); len(params) > 0 { - p.logger.Warn("Missing parameter values", log.FilePath(path), log.String("parameters", strings.Join(params, ", "))) + p.logger.Warn("Missing parameter values", log.FilePath(filePath), log.String("parameters", strings.Join(params, ", "))) } fctx.lines = lines fctx.SourceFormat = sourceFmt - fctx.filepath = path + fctx.filepath = filePath - p.logger.Debug("Context loaded from source", log.FilePath(path)) + p.logger.Debug("Context loaded from source", log.FilePath(filePath)) // the context must be set to conditions before resources for _, c := range fctx.Conditions { @@ -158,7 +161,7 @@ func (p *Parser) ParseFile(ctx context.Context, fsys fs.FS, path string) (fctx * } for name, r := range fctx.Resources { - r.configureResource(name, fsys, path, fctx) + r.configureResource(name, fsys, filePath, fctx) } return fctx, nil @@ -190,10 +193,10 @@ func (p *Parser) parseParams() error { return nil } -func (p *Parser) parseParametersFile(path string) (Parameters, error) { - f, err := p.configsFS.Open(path) +func (p *Parser) parseParametersFile(filePath string) (Parameters, error) { + f, err := p.configsFS.Open(filePath) if err != nil { - return nil, fmt.Errorf("parameters file %q open error: %w", path, err) + return nil, fmt.Errorf("parameters file %q open error: %w", filePath, err) } var parameters Parameters diff --git a/pkg/iac/scanners/cloudformation/parser/parser_test.go b/pkg/iac/scanners/cloudformation/parser/parser_test.go index aa058c4df855..99dd62294eee 100644 --- a/pkg/iac/scanners/cloudformation/parser/parser_test.go +++ b/pkg/iac/scanners/cloudformation/parser/parser_test.go @@ -440,3 +440,52 @@ Conditions: require.NoError(t, err) require.Len(t, files, 1) } + +func Test_TemplateWithNullProperty(t *testing.T) { + src := `AWSTemplateFormatVersion: "2010-09-09" +Resources: + TestBucket: + Type: "AWS::S3::Bucket" + Properties: + BucketName:` + + fsys := testutil.CreateFS(t, map[string]string{ + "main.yaml": src, + }) + + files, err := New().ParseFS(context.TODO(), fsys, ".") + require.NoError(t, err) + require.Len(t, files, 1) + + file := files[0] + + res := file.GetResourceByLogicalID("TestBucket") + + assert.True(t, res.GetProperty("BucketName").IsNil()) +} + +func Test_TemplateWithNullNestedProperty(t *testing.T) { + src := `AWSTemplateFormatVersion: "2010-09-09" +Description: "BAD" +Resources: + TestBucket: + Type: "AWS::S3::Bucket" + Properties: + BucketName: test + PublicAccessBlockConfiguration: + BlockPublicAcls: null` + + fsys := testutil.CreateFS(t, map[string]string{ + "main.yaml": src, + }) + + files, err := New().ParseFS(context.TODO(), fsys, ".") + require.NoError(t, err) + require.Len(t, files, 1) + + file := files[0] + + res := file.GetResourceByLogicalID("TestBucket") + + assert.True(t, res.GetProperty("PublicAccessBlockConfiguration.BlockPublicAcls").IsNil()) +} From 611558e4ce61818330118684274534f26b1fda99 Mon Sep 17 00:00:00 2001 From: Alberto Donato Date: Fri, 8 Nov 2024 08:32:54 +0100 Subject: [PATCH 94/94] fix(terraform): set null value as fallback for missing variables (#7669) --- pkg/iac/scanners/terraform/parser/parser.go | 9 ++++++ .../scanners/terraform/parser/parser_test.go | 30 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/pkg/iac/scanners/terraform/parser/parser.go b/pkg/iac/scanners/terraform/parser/parser.go index 695cbee4fb25..866835d5f8a5 100644 --- a/pkg/iac/scanners/terraform/parser/parser.go +++ b/pkg/iac/scanners/terraform/parser/parser.go @@ -217,6 +217,7 @@ func (p *Parser) Load(ctx context.Context) (*evaluator, error) { "Variable values was not found in the environment or variable files. Evaluating may not work correctly.", log.String("variables", strings.Join(missingVars, ", ")), ) + setNullMissingVariableValues(inputVars, missingVars) } } @@ -268,6 +269,14 @@ func missingVariableValues(blocks terraform.Blocks, inputVars map[string]cty.Val return missing } +// Set null values for missing variables, to allow expressions using them to be +// still be possibly evaluated to a value different than null. +func setNullMissingVariableValues(inputVars map[string]cty.Value, missingVars []string) { + for _, missingVar := range missingVars { + inputVars[missingVar] = cty.NullVal(cty.DynamicPseudoType) + } +} + func (p *Parser) EvaluateAll(ctx context.Context) (terraform.Modules, cty.Value, error) { e, err := p.Load(ctx) diff --git a/pkg/iac/scanners/terraform/parser/parser_test.go b/pkg/iac/scanners/terraform/parser/parser_test.go index 540338afb57f..9c62b958a212 100644 --- a/pkg/iac/scanners/terraform/parser/parser_test.go +++ b/pkg/iac/scanners/terraform/parser/parser_test.go @@ -1801,6 +1801,36 @@ resource "test" "fileset-func" { assert.Equal(t, []string{"a.py", "path/b.py"}, attr.GetRawValue()) } +func TestExprWithMissingVar(t *testing.T) { + files := map[string]string{ + "main.tf": ` +variable "v" { + type = string +} + +resource "test" "values" { + s = "foo-${var.v}" + l1 = ["foo", var.v] + l2 = concat(["foo"], [var.v]) + d1 = {foo = var.v} + d2 = merge({"foo": "bar"}, {"baz": var.v}) +} +`, + } + + resources := parse(t, files).GetResourcesByType("test") + require.Len(t, resources, 1) + + s_attr := resources[0].GetAttribute("s") + require.NotNil(t, s_attr) + assert.Equal(t, "foo-", s_attr.GetRawValue()) + + for _, name := range []string{"l1", "l2", "d1", "d2"} { + attr := resources[0].GetAttribute(name) + require.NotNil(t, attr) + } +} + func TestVarTypeShortcut(t *testing.T) { files := map[string]string{ "main.tf": `