Skip to content

Commit

Permalink
feat: ensure raw report fails if original create scan was unsuccessfull
Browse files Browse the repository at this point in the history
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 <bradley.jones@anchore.com>
  • Loading branch information
bradleyjones committed Feb 14, 2024
1 parent 3c33928 commit f8435dc
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 6 deletions.
2 changes: 2 additions & 0 deletions k8s/harbor-adapter-anchore-skaffold.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
10 changes: 9 additions & 1 deletion pkg/adapter/anchore/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
16 changes: 11 additions & 5 deletions pkg/adapter/anchore/result_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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")
Expand Down
41 changes: 41 additions & 0 deletions pkg/adapter/anchore/result_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
}
}

0 comments on commit f8435dc

Please sign in to comment.