Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update(dependencytrack): better concurrency for fetching apps & no sbom fix #12

Merged
merged 2 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
github.com/jackc/pgx/v5 v5.5.3
github.com/joho/godotenv v1.5.1
github.com/lithammer/fuzzysearch v1.1.8
github.com/nais/dependencytrack v0.0.0-20240208124913-513b3ad1d961
github.com/nais/dependencytrack v0.0.0-20240301095153-b46382e6a8be
github.com/nais/liberator v0.0.0-20240223134957-13b72a76ba9d
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pressly/goose/v3 v3.18.0
Expand Down Expand Up @@ -123,7 +123,7 @@ require (
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc v1.0.4 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/jwx/v2 v2.0.19 // indirect
github.com/lestrrat-go/jwx/v2 v2.0.20 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,8 @@ github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJG
github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
github.com/lestrrat-go/jwx/v2 v2.0.19 h1:ekv1qEZE6BVct89QA+pRF6+4pCpfVrOnEJnTnT4RXoY=
github.com/lestrrat-go/jwx/v2 v2.0.19/go.mod h1:l3im3coce1lL2cDeAjqmaR+Awx+X8Ih+2k8BuHNJ4CU=
github.com/lestrrat-go/jwx/v2 v2.0.20 h1:sAgXuWS/t8ykxS9Bi2Qtn5Qhpakw1wrcjxChudjolCc=
github.com/lestrrat-go/jwx/v2 v2.0.20/go.mod h1:UlCSmKqw+agm5BsOBfEAbTvKsEApaGNqHAEUTv5PJC4=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/libsql/sqlite-antlr4-parser v0.0.0-20230802215326-5cb5bb604475 h1:6PfEMwfInASh9hkN83aR0j4W/eKaAZt/AURtXAXlas0=
Expand Down Expand Up @@ -401,8 +401,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nais/dependencytrack v0.0.0-20240208124913-513b3ad1d961 h1:FtfEwEQq2hWEZFmg3F8Ix9vq6x8o0PF4bEvCn7qwCxw=
github.com/nais/dependencytrack v0.0.0-20240208124913-513b3ad1d961/go.mod h1:zC59yj0La1TS291o/9XSVZ0XAY9UlJS6pUFD3ouHmjU=
github.com/nais/dependencytrack v0.0.0-20240301095153-b46382e6a8be h1:Ri7fb/vmxJySaIxDO1dL9PQIIA4rN1Mtrt2vfD3+Nyo=
github.com/nais/dependencytrack v0.0.0-20240301095153-b46382e6a8be/go.mod h1:kgE6W/n/1C1k+09xVbf7VD8J5J7v0ueHSY9E9vRCM1Y=
github.com/nais/liberator v0.0.0-20240223134957-13b72a76ba9d h1:NA//xj14122osF306Q19oARHyg9JW7g4qJReFO1O3Ds=
github.com/nais/liberator v0.0.0-20240223134957-13b72a76ba9d/go.mod h1:cWThp1WBBbkRFhMI2DQMvBTTEN+6GPzmmh+Xjv8vffE=
github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY=
Expand Down
32 changes: 18 additions & 14 deletions internal/thirdparty/dependencytrack/dependencytrack.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (
"net/http"
"net/url"
"strings"
"sync"
"time"

"github.com/sourcegraph/conc/pool"

"github.com/google/uuid"
"github.com/nais/api/internal/graph/model"
"github.com/nais/api/internal/graph/scalar"
Expand Down Expand Up @@ -137,28 +138,24 @@ func (c *Client) VulnerabilitySummary(ctx context.Context, app *AppInstance) (*m
}

func (c *Client) GetVulnerabilities(ctx context.Context, apps []*AppInstance) ([]*model.Vulnerability, error) {
var wg sync.WaitGroup
now := time.Now()

nodes := make([]*model.Vulnerability, 0)
for _, a := range apps {
wg.Add(1)
go func(app *AppInstance) {
defer wg.Done()
v, err := c.findingsForApp(ctx, app)
p := pool.New().WithMaxGoroutines(10)
for _, app := range apps {
p.Go(func() {
appVulnNode, err := c.findingsForApp(ctx, app)
if err != nil {
c.log.Errorf("retrieveFindings for app %q: %v", app.ID(), err)
return
}
if v == nil {
if appVulnNode == nil {
c.log.Debugf("no findings found in DependencyTrack for app %q", app.ID())
return
}
nodes = append(nodes, v)
}(a)
nodes = append(nodes, appVulnNode)
})
}
wg.Wait()

p.Wait()
c.log.Debugf("DependencyTrack fetch: %v\n", time.Since(now))
return nodes, nil
}
Expand Down Expand Up @@ -186,7 +183,7 @@ func (c *Client) findingsForApp(ctx context.Context, app *AppInstance) (*model.V
findingsLink := fmt.Sprintf("%s/projects/%s/findings", u, p.Uuid)

v.FindingsLink = findingsLink
v.HasBom = p.LastBomImportFormat != ""
v.HasBom = hasBom(p)

if !v.HasBom {
c.log.Debugf("no bom found in DependencyTrack for project %s", p.Name)
Expand All @@ -206,6 +203,13 @@ func (c *Client) findingsForApp(ctx context.Context, app *AppInstance) (*model.V
return v, nil
}

// Due to the nature of the DependencyTrack API, the 'LastBomImportFormat' is not reliable to determine if a project has a BOM.
// The 'LastBomImportFormat' can be empty even if the project has a BOM.
// As a fallback, we can check if projects has registered any components, then we assume that if a project has components, it has a BOM.
func hasBom(p *dependencytrack.Project) bool {
return p.LastBomImportFormat != "" || p.Metrics != nil && p.Metrics.Components > 0
}

func (c *Client) retrieveFindings(ctx context.Context, uuid string) ([]*dependencytrack.Finding, error) {
findings, err := c.client.GetFindings(ctx, uuid)
if err != nil {
Expand Down