Skip to content

Commit 06ea4c3

Browse files
committed
fixes license risks not getting closed correctly, adds tests, fixes packagist dto
1 parent 60233d2 commit 06ea4c3

5 files changed

Lines changed: 72 additions & 16 deletions

File tree

dtos/packagist_dto.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ type PackagistPackageVersion struct {
2828

2929
Type string `json:"type,omitempty"`
3030

31-
Support *PackagistSupport `json:"support,omitempty"`
32-
Funding []PackagistFunding `json:"funding,omitempty"`
31+
Support *PackagistSupport `json:"support,omitempty"`
3332

3433
Require StringMapField `json:"require,omitempty"`
3534
RequireDev StringMapField `json:"require-dev,omitempty"`
@@ -79,10 +78,6 @@ type PackagistSupport struct {
7978
Security string `json:"security,omitempty"`
8079
}
8180

82-
type PackagistFunding struct {
83-
Type string `json:"type,omitempty"`
84-
URL string `json:"url,omitempty"`
85-
}
8681

8782
type StringMapField struct {
8883
Map map[string]any

dtos/vulnevent_dto.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ type VulnEventDTO struct {
5858
ArbitraryJSONData map[string]any `json:"arbitraryJSONData"`
5959

6060
CreatedAt time.Time `json:"createdAt"`
61-
OriginalAssetVersionName *string `json:"originalAssetVersionName,omitempty"`
61+
OriginalAssetVersionName *string `json:"originalAssetVersionName"`
6262
VulnerabilityName string `json:"vulnerabilityName"`
6363
PackageName string `json:"packageName"`
6464
URI string `json:"uri"`

services/license_risk_service.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,8 @@ func (s *LicenseRiskService) UserFixedLicenseRisksByAutomaticRefresh(ctx context
351351
for i := range licenseRisks {
352352
ev := models.NewLicenseDecisionEvent(licenseRisks[i].CalculateHash(), dtos.VulnTypeLicenseRisk, userID, "Automatically fixed by license refresh", artifactName, licenseRisks[i].NewFinalLicense, userAgent)
353353
events[i] = ev
354-
licenseRisksToSave[i] = licenseRisks[i].LicenseRisk
355354
statemachine.Apply(&licenseRisks[i].LicenseRisk, ev)
355+
licenseRisksToSave[i] = licenseRisks[i].LicenseRisk
356356
}
357357
if err := s.licenseRiskRepository.SaveBatch(ctx, tx, licenseRisksToSave); err != nil {
358358
return err

services/open_source_insight_service.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@ import (
1717
)
1818

1919
type openSourceInsightService struct {
20-
httpClient *http.Client
21-
rateLimiter rate.Limiter
20+
httpClient *http.Client
21+
depsDevRateLimiter rate.Limiter
22+
packagistRateLimiter rate.Limiter
2223
}
2324

2425
var _ shared.OpenSourceInsightService = (*openSourceInsightService)(nil) // Ensure openSourceInsightService implements shared.OpenSourceInsightService interface
2526

2627
func NewOpenSourceInsightService() *openSourceInsightService {
2728
return &openSourceInsightService{
28-
httpClient: &http.Client{Transport: utils.EgressTransport},
29-
rateLimiter: *rate.NewLimiter(rate.Every(100*time.Millisecond), 5),
29+
httpClient: &http.Client{Transport: utils.EgressTransport},
30+
depsDevRateLimiter: *rate.NewLimiter(rate.Every(100*time.Millisecond), 5),
31+
packagistRateLimiter: *rate.NewLimiter(rate.Every(100*time.Millisecond), 5),
3032
}
3133
}
3234

@@ -37,7 +39,7 @@ func (s *openSourceInsightService) GetProject(ctx context.Context, projectID str
3739
// make sure the projectID (which is usually a github repository url) is url encoded
3840
projectID = url.PathEscape(projectID)
3941

40-
if err := s.rateLimiter.Wait(ctx); err != nil {
42+
if err := s.depsDevRateLimiter.Wait(ctx); err != nil {
4143
return dtos.OpenSourceInsightsProjectResponse{}, err
4244
}
4345

@@ -124,9 +126,6 @@ func (s *openSourceInsightService) getGoVersion(ctx context.Context, ecosystem,
124126
func (s *openSourceInsightService) getVersion(ctx context.Context, ecosystem, packageName, version string) (dtos.OpenSourceInsightsVersionResponse, error) {
125127
// make sure the package name is url encoded
126128
packageName = url.PathEscape(packageName)
127-
if err := s.rateLimiter.Wait(ctx); err != nil {
128-
return dtos.OpenSourceInsightsVersionResponse{}, err
129-
}
130129

131130
var req *http.Request
132131
var res *http.Response
@@ -135,6 +134,9 @@ func (s *openSourceInsightService) getVersion(ctx context.Context, ecosystem, pa
135134

136135
switch ecosystem {
137136
case "composer":
137+
if err := s.packagistRateLimiter.Wait(ctx); err != nil {
138+
return dtos.OpenSourceInsightsVersionResponse{}, err
139+
}
138140
packageNameDecoded, err := url.PathUnescape(packageName)
139141
if err != nil {
140142
return dtos.OpenSourceInsightsVersionResponse{}, fmt.Errorf("invalid packageName for packagist alternative, could not get version information: %s", packageName)

tests/license_risk_integration_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,65 @@ func TestLicenseRiskArtifactAssociation(t *testing.T) {
9999
})
100100
}
101101

102+
func TestLicenseRiskClosedByRefresh(t *testing.T) {
103+
mockOpenSourceInsightService := mocks.NewOpenSourceInsightService(t)
104+
105+
WithTestAppOptions(t, "../initdb.sql", TestAppOptions{
106+
SuppressLogs: true,
107+
ExtraOptions: []fx.Option{
108+
fx.Decorate(func() shared.OpenSourceInsightService {
109+
return mockOpenSourceInsightService
110+
}),
111+
},
112+
}, func(f *TestFixture) {
113+
_, _, asset, assetVersion := f.CreateOrgProjectAssetAndVersion()
114+
115+
// Component starts with an invalid license
116+
comp := models.Component{
117+
ID: "pkg:npm/bad-license-package@1.0.0",
118+
License: utils.Ptr("PROPRIETARY"),
119+
}
120+
assert.NoError(t, f.DB.Create(&comp).Error)
121+
122+
artifact := models.Artifact{
123+
ArtifactName: "test-artifact",
124+
AssetVersionName: assetVersion.Name,
125+
AssetID: assetVersion.AssetID,
126+
}
127+
assert.NoError(t, f.DB.Create(&artifact).Error)
128+
129+
// Wire the component into the SBOM graph so GetAndSaveLicenseInformation can find it
130+
artifactRoot := "artifact:" + artifact.ArtifactName
131+
infoSourceID := "sbom:DEFAULT@" + artifact.ArtifactName
132+
assert.NoError(t, f.DB.Create(&models.Component{ID: artifactRoot}).Error)
133+
assert.NoError(t, f.DB.Create(&models.Component{ID: infoSourceID}).Error)
134+
assert.NoError(t, f.DB.Create(&models.ComponentDependency{AssetID: assetVersion.AssetID, AssetVersionName: assetVersion.Name, ComponentID: "ROOT", DependencyID: artifactRoot}).Error)
135+
assert.NoError(t, f.DB.Create(&models.ComponentDependency{AssetID: assetVersion.AssetID, AssetVersionName: assetVersion.Name, ComponentID: artifactRoot, DependencyID: infoSourceID}).Error)
136+
assert.NoError(t, f.DB.Create(&models.ComponentDependency{AssetID: assetVersion.AssetID, AssetVersionName: assetVersion.Name, ComponentID: infoSourceID, DependencyID: comp.ID}).Error)
137+
138+
// Open the license risk
139+
err := f.App.LicenseRiskService.FindLicenseRisksInComponents(context.Background(), nil, "system", nil, assetVersion, []models.Component{comp}, artifact.ArtifactName)
140+
assert.NoError(t, err)
141+
142+
risks, err := f.App.LicenseRiskRepository.GetByAssetID(context.Background(), nil, asset.ID)
143+
assert.NoError(t, err)
144+
assert.Len(t, risks, 1)
145+
assert.Equal(t, dtos.VulnStateOpen, risks[0].State)
146+
147+
// Refresh returns a valid license now
148+
mockOpenSourceInsightService.On("GetVersion", mock.Anything, mock.Anything, mock.Anything, mock.Anything).
149+
Return(dtos.OpenSourceInsightsVersionResponse{Licenses: []string{"MIT"}}, nil)
150+
151+
_, err = f.App.ComponentService.GetAndSaveLicenseInformation(context.Background(), nil, assetVersion, nil, true)
152+
assert.NoError(t, err)
153+
154+
risks, err = f.App.LicenseRiskRepository.GetByAssetID(context.Background(), nil, asset.ID)
155+
assert.NoError(t, err)
156+
assert.Len(t, risks, 1)
157+
assert.Equal(t, dtos.VulnStateFixed, risks[0].State, "license risk should be closed after refresh returns a valid license")
158+
})
159+
}
160+
102161
func getSBOMWithWithLicenseRisk() io.Reader {
103162
file, err := os.Open("testdata/sbom-with-license-risk.json")
104163
if err != nil {

0 commit comments

Comments
 (0)