-
Notifications
You must be signed in to change notification settings - Fork 433
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
feat: add vulnerability trend #3130
Merged
Changes from 4 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
d146544
feat: add vulnerability trend
sguiheux 393a956
fix: cr
sguiheux dfacc30
fix lint
sguiheux 944f7fa
add id
sguiheux 2da70ab
feat: add route to ignore a vulnerability
sguiheux 56b7f6c
fix cr
sguiheux c8f99ef
fit TU
sguiheux File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
package workflow | ||
|
||
import ( | ||
"database/sql" | ||
|
||
"github.com/go-gorp/gorp" | ||
|
||
"github.com/ovh/cds/engine/api/application" | ||
"github.com/ovh/cds/engine/api/cache" | ||
"github.com/ovh/cds/engine/api/database/gorpmapping" | ||
"github.com/ovh/cds/engine/api/repositoriesmanager" | ||
"github.com/ovh/cds/sdk" | ||
"github.com/ovh/cds/sdk/log" | ||
) | ||
|
||
// HandleVulnerabilityReport calculate vulnerability trend and save report | ||
func HandleVulnerabilityReport(db gorp.SqlExecutor, cache cache.Store, proj *sdk.Project, nr *sdk.WorkflowNodeRun, workerReport sdk.VulnerabilityWorkerReport) error { | ||
var defaultBranch string | ||
// Get default branch | ||
if nr.VCSServer != "" { | ||
// Get vcs info to known if we are on the default branch or not | ||
projectVCSServer := repositoriesmanager.GetProjectVCSServer(proj, nr.VCSServer) | ||
client, erra := repositoriesmanager.AuthorizedClient(db, cache, projectVCSServer) | ||
if erra != nil { | ||
return sdk.WrapError(sdk.ErrNoReposManagerClientAuth, "HandleVulnerabilityReport> Cannot get repo client %s : %v", nr.VCSServer, erra) | ||
} | ||
|
||
branches, errB := client.Branches(nr.VCSRepository) | ||
if errB != nil { | ||
return sdk.WrapError(errB, "HandleVulnerabilityReport> Cannot list branches for %s/%s", nr.VCSServer, nr.VCSRepository) | ||
} | ||
for _, b := range branches { | ||
if b.Default { | ||
defaultBranch = b.DisplayID | ||
break | ||
} | ||
} | ||
} | ||
|
||
// Get report on the current node run if exist | ||
currentNodeRunReport, err := loadVulnerabilityReport(db, nr.ID) | ||
if err != nil && err != sdk.ErrNotFound { | ||
return sdk.WrapError(err, "HandleVulnerabilityReport> Unable to load vulnerability report") | ||
} | ||
|
||
if err != nil && err == sdk.ErrNotFound { | ||
if err := createNewVulnerabilityReport(db, cache, proj, nr, workerReport, defaultBranch); err != nil { | ||
return sdk.WrapError(err, "HandleVulnerabilityReport> Unable to create no vulnerability report") | ||
} | ||
return nil | ||
} | ||
|
||
currentNodeRunReport.Report.Vulnerabilities = append(currentNodeRunReport.Report.Vulnerabilities, workerReport.Vulnerabilities...) | ||
if currentNodeRunReport.Report.Summary == nil { | ||
currentNodeRunReport.Report.Summary = workerReport.Summary | ||
} else if workerReport.Summary != nil { | ||
for k, v := range workerReport.Summary { | ||
count, ok := currentNodeRunReport.Report.Summary[k] | ||
if !ok { | ||
currentNodeRunReport.Report.Summary[k] = v | ||
} else { | ||
currentNodeRunReport.Report.Summary[k] = count + v | ||
} | ||
} | ||
} | ||
|
||
// Update report | ||
dbReport := dbNodeRunVulenrabilitiesReport(currentNodeRunReport) | ||
if err := dbReport.PostInsert(db); err != nil { | ||
return sdk.WrapError(err, "HandleVulnerabilityReport> Unable to insert report") | ||
} | ||
|
||
// If we are on default branch, save report on application | ||
if defaultBranch != "" && defaultBranch == nr.VCSBranch { | ||
// Save vulnerabilities | ||
if err := application.InsertVulnerabilities(db, currentNodeRunReport.Report.Vulnerabilities, nr.ApplicationID); err != nil { | ||
return sdk.WrapError(err, "HandleVulnerabilityReport> Unable to insert vulnerability") | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func createNewVulnerabilityReport(db gorp.SqlExecutor, cache cache.Store, proj *sdk.Project, nr *sdk.WorkflowNodeRun, workerReport sdk.VulnerabilityWorkerReport, defaultBranch string) error { | ||
// Build current report | ||
nodeRunReport := sdk.WorkflowNodeRunVulnerabilityReport{ | ||
WorkflowID: nr.WorkflowID, | ||
ApplicationID: nr.ApplicationID, | ||
Branch: nr.VCSBranch, | ||
Num: nr.Number, | ||
WorkflowNodeRunID: nr.ID, | ||
WorkflowRunID: nr.WorkflowRunID, | ||
Report: sdk.WorkflowNodeRunVulnerability{ | ||
Vulnerabilities: workerReport.Vulnerabilities, | ||
Summary: workerReport.Summary, | ||
}, | ||
} | ||
|
||
// Get summary from previous run | ||
previousRunReport, err := loadPreviousRunVulnerabilityReport(db, nr) | ||
if err != nil && err != sdk.ErrNotFound { | ||
return sdk.WrapError(err, "HandleVulnerabilityReport> Unable to get previous vulnerability report") | ||
} | ||
nodeRunReport.Report.PreviousRunSummary = previousRunReport | ||
|
||
// Get summary from default branch | ||
if defaultBranch != "" && defaultBranch != nr.VCSBranch { | ||
defaultBranchReport, err := loadLatestRunVulnerabilityReport(db, nr, defaultBranch) | ||
if err != nil && err != sdk.ErrNotFound { | ||
return sdk.WrapError(err, "HandleVulnerabilityReport> Unable to get default branch vulnerability report") | ||
} | ||
nodeRunReport.Report.DefaultBranchSummary = defaultBranchReport | ||
} | ||
|
||
if err := insertVulnerabilityReport(db, nodeRunReport); err != nil { | ||
return sdk.WrapError(err, "HandleVulnerabilityReport> Unable to save vulnerability report") | ||
} | ||
|
||
// If we are on default branch, save report on application | ||
if defaultBranch != "" && defaultBranch == nr.VCSBranch { | ||
if err := application.InsertVulnerabilities(db, nodeRunReport.Report.Vulnerabilities, nr.ApplicationID); err != nil { | ||
return sdk.WrapError(err, "HandleVulnerabilityReport> Unable to update vulnerability") | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func loadPreviousRunVulnerabilityReport(db gorp.SqlExecutor, nr *sdk.WorkflowNodeRun) (map[string]int64, error) { | ||
var dbReport dbNodeRunVulenrabilitiesReport | ||
query := ` | ||
SELECT * FROM workflow_node_run_vulnerability | ||
WHERE application_id = $1 AND workflow_id = $2 AND branch = $3 AND workflow_number < $4 | ||
ORDER BY workflow_number DESC | ||
LIMIT 1 | ||
` | ||
if err := db.SelectOne(&dbReport, query, nr.ApplicationID, nr.WorkflowID, nr.VCSBranch, nr.Number); err != nil { | ||
if err == sql.ErrNoRows { | ||
return nil, sdk.ErrNotFound | ||
} | ||
return nil, sdk.WrapError(err, "loadPreviousRunVulnerabilityReport> Unable to load previous report") | ||
} | ||
return dbReport.Report.Summary, nil | ||
} | ||
|
||
func loadLatestRunVulnerabilityReport(db gorp.SqlExecutor, nr *sdk.WorkflowNodeRun, branch string) (map[string]int64, error) { | ||
var dbReport dbNodeRunVulenrabilitiesReport | ||
query := ` | ||
SELECT * FROM workflow_node_run_vulnerability | ||
WHERE application_id = $1 AND workflow_id = $2 AND branch = $3 | ||
ORDER BY workflow_number DESC, workflow_node_run_id DESC | ||
LIMIT 1 | ||
` | ||
log.Warning("%d %d %s", nr.ApplicationID, nr.WorkflowID, branch) | ||
if err := db.SelectOne(&dbReport, query, nr.ApplicationID, nr.WorkflowID, branch); err != nil { | ||
if err == sql.ErrNoRows { | ||
return nil, sdk.ErrNotFound | ||
} | ||
return nil, sdk.WrapError(err, "loadPreviousRunVulnerabilityReport> Unable to load previous report") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s/loadPreviousRunVulnerabilityReport/loadLatestRunVulnerabilityReport |
||
} | ||
log.Warning("%+v", dbReport.Report.Summary) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. log.Warning?? |
||
return dbReport.Report.Summary, nil | ||
} | ||
|
||
func insertVulnerabilityReport(db gorp.SqlExecutor, report sdk.WorkflowNodeRunVulnerabilityReport) error { | ||
dbReport := dbNodeRunVulenrabilitiesReport(report) | ||
if err := db.Insert(&dbReport); err != nil { | ||
return sdk.WrapError(err, "InsertVulnerabilityReport> Unable to insert report") | ||
} | ||
return nil | ||
} | ||
|
||
// PostGet is a db hook | ||
func (d *dbNodeRunVulenrabilitiesReport) PostGet(db gorp.SqlExecutor) error { | ||
var reportS sql.NullString | ||
query := "SELECT report from workflow_node_run_vulnerability WHERE id = $1" | ||
if err := db.QueryRow(query, d.ID).Scan(&reportS); err != nil { | ||
return sdk.WrapError(err, "dbNodeRunVulenrabilitiesReport.PostGet> Unable to report") | ||
} | ||
|
||
var report sdk.WorkflowNodeRunVulnerability | ||
if err := gorpmapping.JSONNullString(reportS, &report); err != nil { | ||
return sdk.WrapError(err, "dbNodeRunVulenrabilitiesReport.PostGet> Unable to unmarshal report") | ||
} | ||
|
||
d.Report = report | ||
return nil | ||
} | ||
|
||
// PostInsert is a db hook | ||
func (d *dbNodeRunVulenrabilitiesReport) PostInsert(db gorp.SqlExecutor) error { | ||
report, err := gorpmapping.JSONToNullString(d.Report) | ||
if err != nil { | ||
return sdk.WrapError(err, "dbNodeRunVulenrabilitiesReport.PostInsert> Unable to marshal report") | ||
} | ||
query := "UPDATE workflow_node_run_vulnerability set report=$1 WHERE id=$2" | ||
if _, err := db.Exec(query, report, d.ID); err != nil { | ||
return sdk.WrapError(err, "dbNodeRunVulenrabilitiesReport.PostInsert> Unable to insert report") | ||
} | ||
return nil | ||
} | ||
|
||
func loadVulnerabilityReport(db gorp.SqlExecutor, nodeRunID int64) (sdk.WorkflowNodeRunVulnerabilityReport, error) { | ||
var dbReport dbNodeRunVulenrabilitiesReport | ||
query := ` | ||
SELECT * FROM workflow_node_run_vulnerability | ||
WHERE workflow_node_run_id = $1 | ||
` | ||
if err := db.SelectOne(&dbReport, query, nodeRunID); err != nil { | ||
if err == sql.ErrNoRows { | ||
return sdk.WorkflowNodeRunVulnerabilityReport{}, sdk.ErrNotFound | ||
} | ||
return sdk.WorkflowNodeRunVulnerabilityReport{}, sdk.WrapError(err, "loadPreviousRunVulnerabilityReport> Unable to load previous report") | ||
} | ||
return sdk.WorkflowNodeRunVulnerabilityReport(dbReport), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
log.Warning??