From f8435dce9f581a6656ace0ce0ddcd8ebdac70970 Mon Sep 17 00:00:00 2001 From: Bradley Jones Date: Wed, 14 Feb 2024 22:37:09 +0000 Subject: [PATCH] feat: ensure raw report fails if original create scan was unsuccessfull In the case where the harbor formatted report is no longer present in the result store cache, and the raw report request has not progressed past waiting for the create scan then the request should error as it means the original scan create request has failed. Signed-off-by: Bradley Jones --- k8s/harbor-adapter-anchore-skaffold.yaml | 2 ++ pkg/adapter/anchore/adapter.go | 10 +++++- pkg/adapter/anchore/result_store.go | 16 ++++++--- pkg/adapter/anchore/result_store_test.go | 41 ++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/k8s/harbor-adapter-anchore-skaffold.yaml b/k8s/harbor-adapter-anchore-skaffold.yaml index 80aeed2..202768e 100644 --- a/k8s/harbor-adapter-anchore-skaffold.yaml +++ b/k8s/harbor-adapter-anchore-skaffold.yaml @@ -42,6 +42,8 @@ spec: value: "debug" - name: SCANNER_ADAPTER_REGISTRY_TLS_VERIFY value: "false" + - name: SCANNER_ADAPTER_IGNORE_HARBOR_CREDS + value: "false" # To enable api authentication, uncomment this and set it to a good randomized value. Use that same value in the scanner config in Harbor UI with "Bearer" type # - name: "SCANNER_ADAPTER_APIKEY" # value: "apikey123" diff --git a/pkg/adapter/anchore/adapter.go b/pkg/adapter/anchore/adapter.go index b8b0290..0b8addd 100644 --- a/pkg/adapter/anchore/adapter.go +++ b/pkg/adapter/anchore/adapter.go @@ -513,7 +513,15 @@ func (s *HarborScannerAdapter) GetRawVulnerabilityReport(scanID string) (harbor. rawScanID := fmt.Sprintf("%s-raw", scanID) // Used to store just the raw report results in the rawResult store rawResult, _ := resultStore.PopResult(rawScanID) - result := resultStore.GetResult(scanID) + result, resultFound := resultStore.GetResult(scanID) + + // If there is no entry in the cache for the base scanID (harbor formatted report) and the raw ScanCreated is false + // then the original create scan request was unsuccessful, likely due to the image being unable to be added to Anchore + // so we need to fail fast. + if !resultFound && !rawResult.ScanCreated { + log.WithFields(log.Fields{"scanId": scanID}).Debug("scan creation failed, no result found in store for scanId") + return nil, fmt.Errorf("create scan unsuccessful") + } // Check Scan has been created for the non-report report. This ensures the image is in Anchore Enterprise and submitted for analysis. if !rawResult.ScanCreated && !result.ScanCreated { diff --git a/pkg/adapter/anchore/result_store.go b/pkg/adapter/anchore/result_store.go index 075766b..1a2bf84 100644 --- a/pkg/adapter/anchore/result_store.go +++ b/pkg/adapter/anchore/result_store.go @@ -39,7 +39,7 @@ type ResultStore interface { ) // Update a result in the store GetResult( scanID string, - ) VulnerabilityResult // Get a result if it exists + ) (VulnerabilityResult, bool) // Get a result if it exists PopResult( scanID string, ) (VulnerabilityResult, bool) // Returns a result and true if found, false if not (e.g. like hash map interface) @@ -80,16 +80,22 @@ func (m *MemoryResultStore) HasResult(scanID string) bool { return ok && found.IsComplete } -func (m *MemoryResultStore) GetResult(scanID string) VulnerabilityResult { +func (m *MemoryResultStore) GetResult(scanID string) (VulnerabilityResult, bool) { m.mu.Lock() defer m.mu.Unlock() - found := m.Results[scanID] - return found + found, ok := m.Results[scanID] + return found, ok } func (m *MemoryResultStore) PopResult(scanID string) (VulnerabilityResult, bool) { m.mu.Lock() - defer m.mu.Unlock() + defer func() { + m.mu.Unlock() + log.WithField("CacheSize", len(m.Results)).Debug("Cache size - after pop") + }() + + log.WithField("CacheSize", len(m.Results)).Debug("Cache size - before pop") + found, ok := m.Results[scanID] if found.IsComplete { log.WithField("scanId", scanID).Debug("found completed result and removing from store to return to caller") diff --git a/pkg/adapter/anchore/result_store_test.go b/pkg/adapter/anchore/result_store_test.go index cbd4099..7073d43 100644 --- a/pkg/adapter/anchore/result_store_test.go +++ b/pkg/adapter/anchore/result_store_test.go @@ -372,3 +372,44 @@ func TestMemoryResultStore_RequestResult(t *testing.T) { }) } } + +func TestMemoryResultStore_GetResult(t *testing.T) { + type fields struct { + Results map[string]VulnerabilityResult + } + type args struct { + scanID string + } + tests := []struct { + name string + fields fields + args args + want VulnerabilityResult + expectedResult bool + }{ + { + name: "result found", + fields: fields{Results: map[string]VulnerabilityResult{"test1": {ScanID: "test1"}}}, + args: args{"test1"}, + want: VulnerabilityResult{ScanID: "test1"}, + expectedResult: true, + }, + { + name: "no result found", + fields: fields{Results: map[string]VulnerabilityResult{}}, + args: args{"test1"}, + want: VulnerabilityResult{}, + expectedResult: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &MemoryResultStore{ + Results: tt.fields.Results, + } + got, ok := m.GetResult(tt.args.scanID) + assert.Equal(t, tt.want, got) + assert.Equal(t, tt.expectedResult, ok) + }) + } +}