8000 feat(api, ui): add vulnerability trend (#3130) · ovh/cds@4861e20 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit 4861e20

Browse files
sguiheuxfsamin
authored andcommitted
feat(api, ui): add vulnerability trend (#3130)
1 parent 1dc3aa3 commit 4861e20

32 files changed

+727
-111
lines changed

contrib/plugins/plugin-clair/clair.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func (d ClairPlugin) Run(a plugin.IJob) plugin.Result {
9696
}
9797
}
9898

99-
report := sdk.VulnerabilityReport{
99+
report := sdk.VulnerabilityWorkerReport{
100100
Vulnerabilities: vulnerabilities,
101101
Summary: summary,
102102
}

contrib/plugins/plugin-npm-audit-parser/npm-audit-parser.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func (d NpmAuditParserPlugin) Run(j plugin.IJob) plugin.Result {
5454
return plugin.Fail
5555
}
5656

57-
var report sdk.VulnerabilityReport
57+
var report sdk.VulnerabilityWorkerReport
5858
summary := make(map[string]int64)
5959
for _, a := range npmAudit.Advisories {
6060
for _, f := range a.Findings {
@@ -94,6 +94,7 @@ func (d NpmAuditParserPlugin) Run(j plugin.IJob) plugin.Result {
9494

9595
}
9696
}
97+
report.Summary = summary
9798
if err := plugin.SendVulnerabilityReport(j, report); err != nil {
9899
_ = plugin.SendLog(j, "Unable to send report: %s", err)
99100
return plugin.Fail

engine/api/api_routes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ func (api *API) InitRouter() {
162162
r.Handle("/project/{key}/application/{permApplicationName}/variable/audit", r.GET(api.getVariablesAuditInApplicationHandler))
163163
r.Handle("/project/{key}/application/{permApplicationName}/variable/{name}", r.GET(api.getVariableInApplicationHandler), r.POST(api.addVariableInApplicationHandler), r.PUT(api.updateVariableInApplicationHandler), r.DELETE(api.deleteVariableFromApplicationHandler))
164164
r.Handle("/project/{key}/application/{permApplicationName}/variable/{name}/audit", r.GET(api.getVariableAuditInApplicationHandler))
165+
r.Handle("/project/{key}/application/{permApplicationName}/vulnerability/{id}", r.POST(api.postVulnerabilityHandler))
165166
// Application deployment
166167
r.Handle("/project/{key}/application/{permApplicationName}/deployment/config/{platform}", r.POST(api.postApplicationDeploymentStrategyConfigHandler, AllowProvider(true)), r.GET(api.getApplicationDeploymentStrategyConfigHandler), r.DELETE(api.deleteApplicationDeploymentStrategyConfigHandler))
167168
r.Handle("/project/{key}/application/{permApplicationName}/deployment/config", r.GET(api.getApplicationDeploymentStrategiesConfigHandler))

engine/api/application.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ func (api *API) getApplicationHandler() Handler {
244244
withKeys := FormBool(r, "withKeys")
245245
withUsage := FormBool(r, "withUsage")
246246
withDeploymentStrategies := FormBool(r, "withDeploymentStrategies")
247+
withVulnerabilities := FormBool(r, "withVulnerabilities")
247248
branchName := r.FormValue("branchName")
248249
remote := r.FormValue("remote")
249250
versionString := r.FormValue("version")
@@ -267,6 +268,9 @@ func (api *API) getApplicationHandler() Handler {
267268
if withDeploymentStrategies {
268269
loadOptions = append(loadOptions, application.LoadOptions.WithDeploymentStrategies)
269270
}
271+
if withVulnerabilities {
272+
loadOptions = append(loadOptions, application.LoadOptions.WithVulnerabilities)
273+
}
270274

271275
app, errApp := application.LoadByName(api.mustDB(), api.Cache, projectKey, applicationName, getUser(ctx), loadOptions...)
272276
if errApp != nil {

engine/api/application/application_vunerability.go

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,30 @@ import (
88
"github.com/ovh/cds/sdk"
99
)
1010

11-
// InsertVulnerability Insert a new vulnerability
12-
func InsertVulnerability(db gorp.SqlExecutor, v sdk.Vulnerability) error {
13-
dbVuln := dbApplicationVulnerability(v)
14-
if err := db.Insert(&dbVuln); err != nil {
15-
return sdk.WrapError(err, "InsertVulnerability> Unable to insert vulnerabilities")
11+
// InsertVulnerabilities Insert vulnerabilities
12+
func InsertVulnerabilities(db gorp.SqlExecutor, vs []sdk.Vulnerability, appID int64) error {
13+
if _, err := db.Exec("DELETE FROM application_vulnerability WHERE application_id = $1", appID); err != nil {
14+
return sdk.WrapError(err, "InsertVulnerability> Unable to remove old vulnerabilities")
15+
}
16+
for _, v := range vs {
17+
v.ApplicationID = appID
18+
dbVuln := dbApplicationVulnerability(v)
19+
if err := db.Insert(&dbVuln); err != nil {
20+
return sdk.WrapError(err, "InsertVulnerability> Unable to insert vulnerabilities")
21+
}
1622
}
1723
return nil
1824
}
1925

20-
// LoadVulnerabilitiesByRun loads vulnerabilities for the given run
21-
func LoadVulnerabilitiesByRun(db gorp.SqlExecutor, nodeRunID int64) ([]sdk.Vulnerability, error) {
26+
// LoadVulnerabilities load vulnerabilities for the given application
27+
func LoadVulnerabilities(db gorp.SqlExecutor, appID int64) ([]sdk.Vulnerability, error) {
2228
results := make([]dbApplicationVulnerability, 0)
23-
query := `SELECT * FROM application_vulnerability
24-
WHERE workflow_node_run_id=$1`
25-
if _, err := db.Select(&results, query, nodeRunID); err != nil {
29+
query := `SELECT *
30+
FROM application_vulnerability
31+
WHERE application_id = $1`
32+
if _, err := db.Select(&results, query, appID); err != nil {
2633
if err != sql.ErrNoRows {
27-
return nil, sdk.WrapError(err, "LoadVulnerabilitiesByRun> unable to load vulnerabilities for run %d", nodeRunID)
34+
return nil, sdk.WrapError(err, "LoadVulnerabilities> unable to load latest vulnerabilities for application %d", appID)
2835
}
2936
return nil, sdk.ErrNotFound
3037
}
@@ -34,3 +41,27 @@ func LoadVulnerabilitiesByRun(db gorp.SqlExecutor, nodeRunID int64) ([]sdk.Vulne
3441
}
3542
return vulnerabilities, nil
3643
}
44+
45+
// LoadVulnerability load the given vulnerability
46+
func LoadVulnerability(db gorp.SqlExecutor, appID int64, vulnID int64) (sdk.Vulnerability, error) {
47+
var dbVuln dbApplicationVulnerability
48+
query := `SELECT *
49+
FROM application_vulnerability
50+
WHERE application_id = $1 AND id = $2`
51+
if err := db.SelectOne(&dbVuln, query, appID, vulnID); err != nil {
52+
if err != sql.ErrNoRows {
53+
return sdk.Vulnerability{}, sdk.WrapError(err, "LoadVulnerability> unable to load vulnerability %d for application %d", vulnID, appID)
54+
}
55+
return sdk.Vulnerability{}, sdk.ErrNotFound
56+
}
57+
return sdk.Vulnerability(dbVuln), nil
58+
}
59+
60+
// UpdateVulnerability updates a vulnerability
61+
func UpdateVulnerability(db gorp.SqlExecutor, v sdk.Vulnerability) error {
62+
dbVuln := dbApplicationVulnerability(v)
63+
if _, err := db.Update(&dbVuln); err != nil {
64+
return sdk.WrapError(err, "UpdateVulnerability> Unable to update vulnerability")
65+
}
66+
return nil
67+
}

engine/api/application/dao.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ var LoadOptions = struct {
3232
WithClearKeys LoadOptionFunc
3333
WithDeploymentStrategies LoadOptionFunc
3434
WithClearDeploymentStrategies LoadOptionFunc
35+
WithVulnerabilities LoadOptionFunc
3536
}{
3637
Default: &loadDefaultDependencies,
3738
WithVariables: &loadVariables,
@@ -45,6 +46,7 @@ var LoadOptions = struct {
4546
WithClearKeys: &loadClearKeys,
4647
WithDeploymentStrategies: &loadDeploymentStrategies,
4748
WithClearDeploymentStrategies: &loadDeploymentStrategiesWithClearPassword,
49+
WithVulnerabilities: &loadVulnerabilities,
4850
}
4951

5052
// LoadOldApplicationWorkflowToClean load application to clean

engine/api/application/dao_dependencies.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,15 @@ var (
124124
return nil
125125
}
126126

127+
loadVulnerabilities = func(db gorp.SqlExecutor, store cache.Store, app *sdk.Application, u *sdk.User) error {
128+
var err error
129+
app.Vulnerabilities, err = LoadVulnerabilities(db, app.ID)
130+
if err != nil && err != sql.ErrNoRows {
131+
return sdk.WrapError(err, "application.loadVulnerabilities> Unable to load vulnerabilities")
132+
}
133+
return nil
134+
}
135+
127136
loadDeploymentStrategiesWithClearPassword = func(db gorp.SqlExecutor, store cache.Store, app *sdk.Application, u *sdk.User) error {
128137
var err error
129138
app.DeploymentStrategies, err = LoadDeploymentStrategies(db, app.ID, true)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package api
2+
3+
import (
4+
"context"
5+
"net/http"
6+
7+
"github.com/gorilla/mux"
8+
9+
"github.com/ovh/cds/engine/api/application"
10+
"github.com/ovh/cds/sdk"
11+
)
12+
13+
func (api *API) postVulnerabilityHandler() Handler {
14+
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
15+
vars := mux.Vars(r)
16+
key := vars["key"]
17+
appName := vars["permApplicationName"]
18+
19+
vulnID, errV := requestVarInt(r, "id")
20+
if errV != nil {
21+
return sdk.WrapError(errV, "postVulnerabilityHandler> Unable to read ID")
22+
}
23+
24+
var v sdk.Vulnerability
25+
if err := UnmarshalBody(r, &v); err != nil {
26+
return sdk.WrapError(err, "postVulnerabilityHandler> Unable to read body")
27+
}
28+
29+
app, errL := application.LoadByName(api.mustDB(), api.Cache, key, appName, getUser(ctx))
30+
if errL != nil {
31+
return sdk.WrapError(errL, "postVulnerabilityHandler> Unable to load application")
32+
}
33+
34+
vulnDB, errV := application.LoadVulnerability(api.mustDB(), app.ID, vulnID)
35+
if errV != nil {
36+
return sdk.WrapError(errV, "postVulnerabilityHandler> Unable to load vulnerability")
37+
}
38+
39+
vulnDB.Ignored = v.Ignored
40+
41+
if err := application.UpdateVulnerability(api.mustDB(), vulnDB); err != nil {
42+
return sdk.WrapError(err, "postVulnerabilityHandler> Unable to update vulnerability")
43+
}
44+
45+
return WriteJSON(w, vulnDB, http.StatusOK)
46+
}
47+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package api
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
11+
"bytes"
12+
"fmt"
13+
"github.com/ovh/cds/engine/api/application"
14+
"github.com/ovh/cds/engine/api/test"
15+
"github.com/ovh/cds/engine/api/test/assets"
16+
"github.com/ovh/cds/sdk"
17+
)
18+
19+
func Test_postVulnerabilityHandler(t *testing.T) {
20+
api, db, router := newTestAPI(t)
21+
22+
//Create admin user
23+
u, pass := assets.InsertAdminUser(api.mustDB())
24+
25+
//Insert Project
26+
pkey := sdk.RandomString(10)
27+
proj := assets.InsertTestProject(t, db, api.Cache, pkey, pkey, u)
28+
29+
app := &sdk.Application{
30+
Name: sdk.RandomString(10),
31+
}
32+
if err := application.Insert(api.mustDB(), api.Cache, proj, app, u); err != nil {
33+
t.Fatal(err)
34+
}
35+
36+
v := sdk.Vulnerability{}
37+
v.ApplicationID = app.ID
38+
39+
assert.NoError(t, application.InsertVulnerabilities(db, []sdk.Vulnerability{v}, app.ID))
40+
41+
vulns, err := application.LoadVulnerabilities(db, app.ID)
42+
assert.NoError(t, err)
43+
44+
vars := map[string]string{
45+
"key": proj.Key,
46+
"permApplicationName": app.Name,
47+
"id": fmt.Sprintf("%d", vulns[0].ID),
48+
}
49+
50+
uri := router.GetRoute("POST", api.postVulnerabilityHandler, vars)
51+
52+
vulns[0].Ignored = true
53+
jsonBody, _ := json.Marshal(vulns[0])
54+
body := bytes.NewBuffer(jsonBody)
55+
56+
req, err := http.NewRequest("POST", uri, body)
57+
test.NoError(t, err)
58+
assets.AuthentifyRequest(t, req, u, pass)
59+
60+
// Do the request
61+
w := httptest.NewRecorder()
62+
router.Mux.ServeHTTP(w, req)
63+
assert.Equal(t, 200, w.Code)
64+
65+
}

engine/api/workflow/dao_node_run.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"github.com/go-gorp/gorp"
1111
"github.com/ovh/venom"
1212

13-
"github.com/ovh/cds/engine/api/application"
1413
"github.com/ovh/cds/engine/api/cache"
1514
"github.com/ovh/cds/engine/api/database/gorpmapping"
1615
"github.com/ovh/cds/engine/api/repositoriesmanager"
@@ -94,11 +93,11 @@ func LoadNodeRun(db gorp.SqlExecutor, projectkey, workflowname string, number, i
9493
r.Coverage = cov
9594
}
9695
if loadOpts.WithVulnerabilities {
97-
vulns, errV := application.LoadVulnerabilitiesByRun(db, r.ID)
98-
if errV != nil && errV != sdk.ErrNotFound {
99-
return nil, sdk.WrapError(errV, "LoadNodeRun>Error loading vulnerabilities for run %d", r.ID)
96+
vuln, errV := loadVulnerabilityReport(db, r.ID)
97+
if errV != nil {
98+
return nil, sdk.WrapError(errV, "LoadNodeRun>Error vulnerability report coverage for run %d", r.ID)
10099
}
101-
r.Vulnerabilities = vulns
100+
r.VulnerabilitiesReport = vuln
102101
}
103102
return r, nil
104103

0 commit comments

Comments
 (0)
0