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

fix(plugin:clair,ui,api): save and render vulnerabilities, clair panic #5234

Merged
merged 3 commits into from
Jun 10, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
28 changes: 16 additions & 12 deletions contrib/grpcplugins/action/clair/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ go 1.13

replace github.com/ovh/cds => ../../../../

replace github.com/docker/docker => github.com/docker/engine v0.0.0-20180816081446-320063a2ad06
replace github.com/docker/docker => github.com/moby/moby v17.12.0-ce-rc1.0.20200528182317-b47e74255811+incompatible

replace github.com/Sirupsen/logrus v1.4.0 => github.com/sirupsen/logrus v1.4.0
replace github.com/Sirupsen/logrus => github.com/sirupsen/logrus v1.6.0

replace github.com/codegangsta/cli v1.22.2 => github.com/urfave/cli v1.22.2

Expand All @@ -15,24 +15,28 @@ replace github.com/prometheus/client_golang v1.1.0 => github.com/prometheus/clie
replace github.com/opencontainers/runc v0.1.1 => github.com/opencontainers/runc v1.0.0-rc9

require (
github.com/containerd/containerd v1.3.2 // indirect
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb // indirect
github.com/Microsoft/hcsshim v0.8.9 // indirect
github.com/Sirupsen/logrus v0.0.0-00010101000000-000000000000 // indirect
github.com/containerd/containerd v1.3.4 // indirect
github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb // indirect
github.com/docker/distribution v2.7.1+incompatible
github.com/docker/docker v1.13.1
github.com/docker/go-metrics v0.0.1 // indirect
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
github.com/golang/protobuf v1.3.2
github.com/golang/protobuf v1.4.2
github.com/jgsqware/xnet v0.0.0-20170203143001-13630f0737d2
github.com/mattn/go-shellwords v1.0.6 // indirect
github.com/mattn/go-shellwords v1.0.10 // indirect
github.com/mholt/archiver v3.1.1+incompatible
github.com/opencontainers/go-digest v1.0.0-rc1
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/runc v0.1.1 // indirect
github.com/opencontainers/runtime-spec v1.0.1 // indirect
github.com/opencontainers/selinux v1.3.0 // indirect
github.com/opencontainers/runtime-spec v1.0.2 // indirect
github.com/opencontainers/selinux v1.5.2 // indirect
github.com/ovh/cds v0.0.0-00010101000000-000000000000
github.com/prometheus/client_golang v1.1.0
github.com/quay/clair/v2 v2.1.1
github.com/spf13/viper v1.5.0
github.com/quay/clair/v2 v2.1.4
github.com/spf13/viper v1.7.0
github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect
github.com/vbatts/tar-split v0.11.1 // indirect
golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a
golang.org/x/net v0.0.0-20200602114024-627f9648deb9
)
281 changes: 195 additions & 86 deletions contrib/grpcplugins/action/clair/go.sum

Large diffs are not rendered by default.

5 changes: 0 additions & 5 deletions contrib/grpcplugins/action/clair/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ func (actPlugin *clairActionPlugin) Run(ctx context.Context, q *actionplugin.Act
fmt.Printf("Creating report")

var vulnerabilities []sdk.Vulnerability
summary := make(map[string]int64)
if analysis.MostRecentLayer().Layer != nil {
for _, feat := range analysis.MostRecentLayer().Layer.Features {
for _, vuln := range feat.Vulnerabilities {
Expand All @@ -83,16 +82,12 @@ func (actPlugin *clairActionPlugin) Run(ctx context.Context, q *actionplugin.Act
Title: fmt.Sprintf("%s %s", feat.Name, feat.Version),
}
vulnerabilities = append(vulnerabilities, v)

count := summary[v.Severity]
summary[v.Severity] = count + 1
}
}
}

report := sdk.VulnerabilityWorkerReport{
Vulnerabilities: vulnerabilities,
Summary: summary,
Type: "docker",
}
if err := grpcplugins.SendVulnerabilityReport(actPlugin.HTTPPort, report); err != nil {
Expand Down
8 changes: 1 addition & 7 deletions contrib/grpcplugins/action/npm-audit-parser/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (actPlugin *npmAuditParserActionPlugin) Run(ctx context.Context, q *actionp
}

var report sdk.VulnerabilityWorkerReport
summary := make(map[string]int64)

for _, a := range npmAudit.Advisories {
for _, f := range a.Findings {
if len(a.CVES) > 0 {
Expand All @@ -63,8 +63,6 @@ func (actPlugin *npmAuditParserActionPlugin) Run(ctx context.Context, q *actionp
Version: f.Version,
}
report.Vulnerabilities = append(report.Vulnerabilities, v)
count := summary[v.Severity]
summary[v.Severity] = count + 1
}
} else {
v := sdk.Vulnerability{
Expand All @@ -79,14 +77,10 @@ func (actPlugin *npmAuditParserActionPlugin) Run(ctx context.Context, q *actionp
Version: f.Version,
}
report.Vulnerabilities = append(report.Vulnerabilities, v)
count := summary[v.Severity]
summary[v.Severity] = count + 1
}

}
}
report.Type = "js"
report.Summary = summary
if err := grpcplugins.SendVulnerabilityReport(actPlugin.HTTPPort, report); err != nil {
return actionplugin.Fail("Unable to send report: %s", err)
}
Expand Down
38 changes: 24 additions & 14 deletions engine/api/application/application_vunerability.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
// LoadVulnerabilitiesSummary compute vulnerabilities summary
func LoadVulnerabilitiesSummary(db gorp.SqlExecutor, appID int64) (map[string]float64, error) {
query := `
SELECT json_object_agg(severity, nb)::TEXT
SELECT json_object_agg(severity, nb)::TEXT
FROM (
SELECT count(id) AS nb, severity
SELECT count(id) AS nb, severity
FROM application_vulnerability
WHERE application_id = $1
GROUP BY severity
Expand All @@ -24,42 +24,52 @@ func LoadVulnerabilitiesSummary(db gorp.SqlExecutor, appID int64) (map[string]fl
var summary map[string]float64
var result sql.NullString
if err := db.QueryRow(query, appID).Scan(&result); err != nil {
return nil, sdk.WrapError(err, "LoadVulnerabilitiesSummary")
return nil, sdk.WithStack(err)
}

if err := gorpmapping.JSONNullString(result, &summary); err != nil {
return nil, sdk.WrapError(err, "Unable to unmarshal summary")
return nil, sdk.WrapError(err, "unable to unmarshal summary")
}
return summary, nil
}

// InsertVulnerabilities Insert vulnerabilities
func InsertVulnerabilities(db gorp.SqlExecutor, vs []sdk.Vulnerability, appID int64, t string) error {
if _, err := db.Exec("DELETE FROM application_vulnerability WHERE application_id = $1 AND type = $2", appID, t); err != nil {
return sdk.WrapError(err, "Unable to remove old vulnerabilities")
}
func InsertVulnerabilities(db gorp.SqlExecutor, vs []sdk.Vulnerability, appID int64) error {
for _, v := range vs {
v.ApplicationID = appID
v.Type = t
dbVuln := dbApplicationVulnerability(v)
if err := db.Insert(&dbVuln); err != nil {
return sdk.WrapError(err, "Unable to insert vulnerabilities")
return sdk.WrapError(err, "unable to insert vulnerabilities")
}
}
return nil
}

// DeleteVulnerabilitiesByApplicationIDAndType removes all the vulnerabilities for given application and type.
func DeleteVulnerabilitiesByApplicationIDAndType(db gorp.SqlExecutor, applicationID int64, vulnerabilityType string) error {
if _, err := db.Exec(`
DELETE FROM application_vulnerability
WHERE application_id = $1
AND type = $2
`, applicationID, vulnerabilityType); err != nil {
return sdk.WrapError(err, "unable to remove vulnerabilities with type %s for application with id %d", vulnerabilityType, applicationID)
}
return nil
}

// LoadVulnerabilities load vulnerabilities for the given application
func LoadVulnerabilities(db gorp.SqlExecutor, appID int64) ([]sdk.Vulnerability, error) {
results := make([]dbApplicationVulnerability, 0)
query := `SELECT *
FROM application_vulnerability
WHERE application_id = $1`
query := `
SELECT *
FROM application_vulnerability
WHERE application_id = $1
`
if _, err := db.Select(&results, query, appID); err != nil {
if err != sql.ErrNoRows {
return nil, sdk.WrapError(err, "unable to load latest vulnerabilities for application %d", appID)
}
return nil, sdk.WithStack(sdk.ErrNotFound)
return nil, nil
}
vulnerabilities := make([]sdk.Vulnerability, len(results))
for i := range results {
Expand Down
4 changes: 2 additions & 2 deletions engine/api/application/dao_dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ var (
loadVulnerabilities = func(db gorp.SqlExecutor, app *sdk.Application) error {
var err error
app.Vulnerabilities, err = LoadVulnerabilities(db, app.ID)
if err != nil && sdk.Cause(err) != sql.ErrNoRows {
return sdk.WrapError(err, "Unable to load vulnerabilities")
if err != nil {
return sdk.WrapError(err, "unable to load vulnerabilities")
}
return nil
}
Expand Down
8 changes: 3 additions & 5 deletions engine/api/application_vulnerability_test.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package api

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"

"bytes"
"fmt"

"github.com/ovh/cds/engine/api/application"
"github.com/ovh/cds/engine/api/test"
"github.com/ovh/cds/engine/api/test/assets"
Expand All @@ -37,7 +36,7 @@ func Test_postVulnerabilityHandler(t *testing.T) {
v := sdk.Vulnerability{}
v.ApplicationID = app.ID

assert.NoError(t, application.InsertVulnerabilities(db, []sdk.Vulnerability{v}, app.ID, "docker"))
assert.NoError(t, application.InsertVulnerabilities(db, []sdk.Vulnerability{v}, app.ID))

vulns, err := application.LoadVulnerabilities(db, app.ID)
assert.NoError(t, err)
Expand All @@ -62,5 +61,4 @@ func Test_postVulnerabilityHandler(t *testing.T) {
w := httptest.NewRecorder()
router.Mux.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)

}
11 changes: 6 additions & 5 deletions engine/api/workflow/dao_node_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,15 @@ func LoadNodeRun(db gorp.SqlExecutor, projectkey, workflowname string, number, i
r.Coverage = cov
}
if loadOpts.WithVulnerabilities {
vuln, errV := loadVulnerabilityReport(db, r.ID)
if errV != nil && !sdk.ErrorIs(errV, sdk.ErrNotFound) {
return nil, sdk.WrapError(errV, "LoadNodeRun>Error vulnerability report coverage for run %d", r.ID)
vuln, err := loadVulnerabilityReport(db, r.ID)
if err != nil && !sdk.ErrorIs(err, sdk.ErrNotFound) {
return nil, sdk.WrapError(err, "vulnerability report coverage for run %d", r.ID)
}
if vuln != nil {
r.VulnerabilitiesReport = *vuln
}
r.VulnerabilitiesReport = vuln
}
return r, nil

}

//LoadNodeRunByNodeJobID load a specific node run on a workflow from a node job run id
Expand Down
Loading