Skip to content

Commit faf16c2

Browse files
Merge branch 'main' into containers-cli-1.10
2 parents 198f634 + 958e7ce commit faf16c2

File tree

5 files changed

+113
-65
lines changed

5 files changed

+113
-65
lines changed

internal/services/ossrealtime/oss-realtime.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ossrealtime
33
import (
44
"fmt"
55
"log"
6+
"strings"
67

78
"github.com/Checkmarx/manifest-parser/pkg/parser"
89
"github.com/Checkmarx/manifest-parser/pkg/parser/models"
@@ -53,11 +54,11 @@ func (o *OssRealtimeService) RunOssRealtimeScan(filePath string) (*OssPackageRes
5354
response, toScan := prepareScan(pkgs)
5455

5556
if len(toScan.Packages) > 0 {
56-
packageMap := createPackageMap(pkgs)
5757
result, err := o.scanAndCache(toScan)
5858
if err != nil {
5959
return nil, errors.Wrap(err, "scanning packages via realtime service")
6060
}
61+
packageMap := createPackageMap(pkgs)
6162
enrichResponseWithRealtimeScannerResults(response, result, packageMap)
6263
}
6364
return response, nil
@@ -199,12 +200,33 @@ func (o *OssRealtimeService) scanAndCache(requestPackages *wrappers.RealtimeScan
199200
return nil, errors.New("empty response from oss-realtime scan")
200201
}
201202

202-
if err = osscache.AppendToCache(result); err != nil {
203+
versionMapping := createVersionMapping(requestPackages, result)
204+
205+
if err := osscache.AppendToCache(result, versionMapping); err != nil {
203206
log.Printf("ossrealtime: failed to update cache: %v", err)
204207
}
208+
205209
return result, nil
206210
}
207211

212+
func createVersionMapping(requestPackages *wrappers.RealtimeScannerPackageRequest, result *wrappers.RealtimeScannerPackageResponse) map[string]string {
213+
requestedPackagesVersion := make(map[string]string)
214+
for _, pkg := range requestPackages.Packages {
215+
key := fmt.Sprintf("%s|%s", strings.ToLower(pkg.PackageManager), strings.ToLower(pkg.PackageName))
216+
requestedPackagesVersion[key] = pkg.Version
217+
}
218+
219+
versionMapping := make(map[string]string)
220+
for _, resPkg := range result.Packages {
221+
key := fmt.Sprintf("%s|%s", strings.ToLower(resPkg.PackageManager), strings.ToLower(resPkg.PackageName))
222+
if requestedVersion, found := requestedPackagesVersion[key]; found {
223+
versionMapping[osscache.GenerateCacheKey(resPkg.PackageManager, resPkg.PackageName, resPkg.Version)] = requestedVersion
224+
}
225+
}
226+
227+
return versionMapping
228+
}
229+
208230
// pkgToRequest transforms a parsed package into a scan request.
209231
func pkgToRequest(pkg *models.Package) wrappers.RealtimeScannerPackage {
210232
return wrappers.RealtimeScannerPackage{
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package osscache
2+
3+
import "github.com/checkmarx/ast-cli/internal/wrappers"
4+
5+
type OssCacheVulnerabilityMapper struct{}
6+
7+
func NewOssCacheVulnerabilityMapper() *OssCacheVulnerabilityMapper {
8+
return &OssCacheVulnerabilityMapper{}
9+
}
10+
11+
func (o *OssCacheVulnerabilityMapper) FromRealtimeScannerVulnerability(in []wrappers.RealtimeScannerVulnerability) []Vulnerability {
12+
out := make([]Vulnerability, len(in))
13+
for i, v := range in {
14+
out[i] = Vulnerability{
15+
CVE: v.CVE,
16+
Description: v.Description,
17+
Severity: v.Severity,
18+
}
19+
}
20+
return out
21+
}

internal/services/ossrealtime/osscache/oss-realtime-cache.go

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"fmt"
66
"os"
7+
"strings"
78
"time"
89

910
"github.com/checkmarx/ast-cli/internal/wrappers"
@@ -58,7 +59,8 @@ func WriteCache(cache Cache, cacheTTL *time.Time) error {
5859
return nil
5960
}
6061

61-
func AppendToCache(packages *wrappers.RealtimeScannerPackageResponse) error {
62+
func AppendToCache(packages *wrappers.RealtimeScannerPackageResponse, versionMapping map[string]string) error {
63+
vulnerabilityMapper := NewOssCacheVulnerabilityMapper()
6264
cache := ReadCache()
6365
if cache == nil {
6466
cache = &Cache{
@@ -68,28 +70,35 @@ func AppendToCache(packages *wrappers.RealtimeScannerPackageResponse) error {
6870
}
6971

7072
for _, pkg := range packages.Packages {
71-
vulnerabilities := make([]Vulnerability, 0)
72-
if pkg.Status != "Unknown" {
73-
for _, v := range pkg.Vulnerabilities {
74-
vulnerabilities = append(vulnerabilities, Vulnerability{
75-
CVE: v.CVE,
76-
Description: v.Description,
77-
Severity: v.Severity,
78-
})
73+
if pkg.Status == "Unknown" {
74+
continue
75+
}
76+
77+
key := GenerateCacheKey(pkg.PackageManager, pkg.PackageName, pkg.Version)
78+
vulnerabilities := vulnerabilityMapper.FromRealtimeScannerVulnerability(pkg.Vulnerabilities)
79+
80+
if requestedVersion, exists := versionMapping[key]; exists {
81+
if !strings.EqualFold(requestedVersion, pkg.Version) && strings.EqualFold("latest", requestedVersion) {
82+
cache.Packages = append(cache.Packages, createPackageEntry(&pkg, requestedVersion, vulnerabilities))
7983
}
80-
cache.Packages = append(cache.Packages, PackageEntry{
81-
PackageID: GenerateCacheKey(pkg.PackageManager, pkg.PackageName, pkg.Version),
82-
PackageManager: pkg.PackageManager,
83-
PackageName: pkg.PackageName,
84-
PackageVersion: pkg.Version,
85-
Status: pkg.Status,
86-
Vulnerabilities: vulnerabilities,
87-
})
8884
}
85+
cache.Packages = append(cache.Packages, createPackageEntry(&pkg, pkg.Version, vulnerabilities))
8986
}
87+
9088
return WriteCache(*cache, &cache.TTL)
9189
}
9290

91+
func createPackageEntry(pkg *wrappers.RealtimeScannerResults, version string, vulnerabilities []Vulnerability) PackageEntry {
92+
return PackageEntry{
93+
PackageID: GenerateCacheKey(pkg.PackageManager, pkg.PackageName, version),
94+
PackageManager: pkg.PackageManager,
95+
PackageName: pkg.PackageName,
96+
PackageVersion: version,
97+
Status: pkg.Status,
98+
Vulnerabilities: vulnerabilities,
99+
}
100+
}
101+
93102
func GetCacheFilePath() string {
94103
tempFolder := os.TempDir()
95104
return fmt.Sprint(tempFolder, "/", cacheFileName)

internal/services/ossrealtime/osscache/oss-realtime-cache_test.go

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package osscache
33
import (
44
"os"
55
"reflect"
6+
"strings"
67
"testing"
78
"time"
89

@@ -26,7 +27,6 @@ func TestWriteAndReadCache(t *testing.T) {
2627
cacheFile := GetCacheFilePath()
2728
defer os.Remove(cacheFile)
2829

29-
// prepare a cache object
3030
ttl := time.Now().Add(time.Hour).Truncate(time.Second)
3131
want := Cache{
3232
TTL: ttl,
@@ -40,12 +40,10 @@ func TestWriteAndReadCache(t *testing.T) {
4040
},
4141
}
4242

43-
// write it
4443
if err := WriteCache(want, &want.TTL); err != nil {
4544
t.Fatalf("WriteCache() error = %v; want no error", err)
4645
}
4746

48-
// read it back
4947
got := ReadCache()
5048
if got == nil {
5149
t.Fatal("ReadCache() returned nil; want non-nil")
@@ -61,27 +59,24 @@ func TestAppendToCache(t *testing.T) {
6159
cacheFile := GetCacheFilePath()
6260
defer os.Remove(cacheFile)
6361

64-
// first batch
6562
first := &wrappers.RealtimeScannerPackageResponse{
6663
Packages: []wrappers.RealtimeScannerResults{
6764
{PackageManager: "npm", PackageName: "lodash", Version: "4.17.21", Status: "OK"},
6865
},
6966
}
70-
if err := AppendToCache(first); err != nil {
67+
if err := AppendToCache(first, nil); err != nil {
7168
t.Fatalf("AppendToCache(first) error = %v; want no error", err)
7269
}
7370

74-
// second batch
7571
second := &wrappers.RealtimeScannerPackageResponse{
7672
Packages: []wrappers.RealtimeScannerResults{
7773
{PackageManager: "npm", PackageName: "express", Version: "4.17.1", Status: "Malicious"},
7874
},
7975
}
80-
if err := AppendToCache(second); err != nil {
76+
if err := AppendToCache(second, nil); err != nil {
8177
t.Fatalf("AppendToCache(second) error = %v; want no error", err)
8278
}
8379

84-
// now read & verify we have both entries
8580
cache := ReadCache()
8681
if cache == nil {
8782
t.Fatal("ReadCache() returned nil; want non-nil")
@@ -107,44 +102,46 @@ func TestAppendToCache(t *testing.T) {
107102
}
108103
}
109104

110-
func Test_buildCacheMap(t *testing.T) {
111-
type args struct {
112-
cache Cache
113-
}
114-
tests := []struct {
115-
name string
116-
args args
117-
want map[string]string
118-
}{
119-
// TODO: Add test cases.
120-
}
121-
for _, tt := range tests {
122-
t.Run(tt.name, func(t *testing.T) {
123-
if got := BuildCacheMap(tt.args.cache); !reflect.DeepEqual(got, tt.want) {
124-
t.Errorf("buildCacheMap() = %v, want %v", got, tt.want)
125-
}
126-
})
105+
func TestAppendToCache_WithVersionMapping(t *testing.T) {
106+
cacheFile := GetCacheFilePath()
107+
var latestVersionInCache bool
108+
var exactVersionInCache bool
109+
defer os.Remove(cacheFile)
110+
111+
pkgResponse := &wrappers.RealtimeScannerPackageResponse{
112+
Packages: []wrappers.RealtimeScannerResults{
113+
{PackageManager: "npm", PackageName: "lodash", Version: "4.17.21", Status: "OK"},
114+
{PackageManager: "npm", PackageName: "express", Version: "1.1.1", Status: "Malicious"},
115+
},
116+
}
117+
versionMapping := map[string]string{
118+
"npm-express-1.1.1": "latest",
119+
}
120+
if err := AppendToCache(pkgResponse, versionMapping); err != nil {
121+
t.Fatalf("AppendToCache(first) error = %v; want no error", err)
127122
}
128-
}
129123

130-
func Test_cacheKey(t *testing.T) {
131-
type args struct {
132-
manager string
133-
name string
134-
version string
135-
}
136-
tests := []struct {
137-
name string
138-
args args
139-
want string
140-
}{
141-
// TODO: Add test cases.
142-
}
143-
for _, tt := range tests {
144-
t.Run(tt.name, func(t *testing.T) {
145-
if got := GenerateCacheKey(tt.args.manager, tt.args.name, tt.args.version); got != tt.want {
146-
t.Errorf("cacheKey() = %v, want %v", got, tt.want)
147-
}
148-
})
124+
cache := ReadCache()
125+
if cache == nil {
126+
t.Fatal("ReadCache() returned nil; want non-nil")
149127
}
128+
129+
var got []wrappers.RealtimeScannerResults
130+
for _, e := range cache.Packages {
131+
pkg := wrappers.RealtimeScannerResults{
132+
PackageManager: e.PackageManager,
133+
PackageName: e.PackageName,
134+
Version: e.PackageVersion,
135+
Status: e.Status,
136+
}
137+
got = append(got, pkg)
138+
if strings.EqualFold(pkg.PackageName, "express") && strings.EqualFold(pkg.Version, "latest") {
139+
latestVersionInCache = true
140+
} else if strings.EqualFold(pkg.PackageName, "express") && strings.EqualFold(pkg.Version, "1.1.1") {
141+
exactVersionInCache = true
142+
}
143+
}
144+
asserts.True(t, latestVersionInCache, "Expected latest version of express to be in cache")
145+
asserts.True(t, exactVersionInCache, "Expected exact versions of express to be in cache")
146+
asserts.Greater(t, len(got), len(pkgResponse.Packages)) // Ensure that the cache contains the exact version and the latest version of express
150147
}

internal/services/ossrealtime/osscache/types.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ type PackageEntry struct {
1212
Status string `json:"status"`
1313
Vulnerabilities []Vulnerability `json:"vulnerabilities"`
1414
}
15-
1615
type Vulnerability struct {
1716
CVE string `json:"cve"`
1817
Description string `json:"description"`

0 commit comments

Comments
 (0)