@ -96,7 +96,6 @@ func (av *AbstractVulnerability) ToVulnerability(fixedInNodes []string) *Vulnera
}
}
// InsertVulnerabilities inserts or updates several vulnerabilities in the database in one transaction
// InsertVulnerabilities inserts or updates several vulnerabilities in the database in one transaction
// It ensures that a vulnerability can't be fixed by two packages belonging the same Branch.
// During an update, if the vulnerability was previously fixed by a version in a branch and a new package of that branch is specified, the previous one is deleted
// During an update, if the vulnerability was previously fixed by a version in a branch and a new package of that branch is specified, the previous one is deleted
// Otherwise, it simply adds the defined packages, there is currently no way to delete affected packages.
// Otherwise, it simply adds the defined packages, there is currently no way to delete affected packages.
//
//
@ -110,13 +109,15 @@ func InsertVulnerabilities(vulnerabilities []*Vulnerability) ([]Notification, er
var err error
var err error
t := cayley . NewTransaction ( )
t := cayley . NewTransaction ( )
cachedVulnerabilities := make ( map [ string ] * Vulnerability )
cachedVulnerabilities := make ( map [ string ] * Vulnerability )
var notifications [ ] Notification
newVulnerabilityNotifications := make ( map [ string ] * NewVulnerabilityNotification )
newVulnerabilityNotifications := make ( map [ string ] * NewVulnerabilityNotification )
vulnerabilityPriorityIncreasedNotifications := make ( map [ string ] * VulnerabilityPriorityIncreasedNotification )
vulnerabilityPriorityIncreasedNotifications := make ( map [ string ] * VulnerabilityPriorityIncreasedNotification )
vulnerabilityPackageChangedNotifications := make ( map [ string ] * VulnerabilityPackageChangedNotification )
vulnerabilityPackageChangedNotifications := make ( map [ string ] * VulnerabilityPackageChangedNotification )
// Iterate over all the vulnerabilities we need to insert/update
// Iterate over all the vulnerabilities we need to insert/update
for _ , vulnerability := range vulnerabilities {
for _ , vulnerability := range vulnerabilities {
// Is the vulnerability already existing ?
// Check if the vulnerability already exists
existingVulnerability , _ := cachedVulnerabilities [ vulnerability . ID ]
existingVulnerability , _ := cachedVulnerabilities [ vulnerability . ID ]
if existingVulnerability == nil {
if existingVulnerability == nil {
existingVulnerability , err = FindOneVulnerability ( vulnerability . ID , FieldVulnerabilityAll )
existingVulnerability , err = FindOneVulnerability ( vulnerability . ID , FieldVulnerabilityAll )
@ -128,23 +129,6 @@ func InsertVulnerabilities(vulnerabilities []*Vulnerability) ([]Notification, er
}
}
}
}
// Don't allow inserting/updating a vulnerability which is fixed in two packages of the same branch
if len ( vulnerability . FixedInNodes ) > 0 {
fixedInPackages , err := FindAllPackagesByNodes ( vulnerability . FixedInNodes , [ ] string { FieldPackageOS , FieldPackageName } )
if err != nil {
return [ ] Notification { } , err
}
fixedInBranches := make ( map [ string ] struct { } )
for _ , fixedInPackage := range fixedInPackages {
branch := fixedInPackage . Branch ( )
if _ , branchExists := fixedInBranches [ branch ] ; branchExists {
log . Warningf ( "could not insert vulnerability %s because it is fixed in two packages of the same branch" , vulnerability . ID )
return [ ] Notification { } , cerrors . NewBadRequestError ( "could not insert a vulnerability which is fixed in two packages of the same branch" )
}
fixedInBranches [ branch ] = struct { } { }
}
}
// Insert/Update vulnerability
// Insert/Update vulnerability
if existingVulnerability == nil {
if existingVulnerability == nil {
// The vulnerability does not exist, create it
// The vulnerability does not exist, create it
@ -165,7 +149,6 @@ func InsertVulnerabilities(vulnerabilities []*Vulnerability) ([]Notification, er
// Insert it
// Insert it
vulnerability . Node = vulnerability . GetNode ( )
vulnerability . Node = vulnerability . GetNode ( )
cachedVulnerabilities [ vulnerability . ID ] = vulnerability
t . AddQuad ( cayley . Quad ( vulnerability . Node , FieldIs , FieldVulnerabilityIsValue , "" ) )
t . AddQuad ( cayley . Quad ( vulnerability . Node , FieldIs , FieldVulnerabilityIsValue , "" ) )
t . AddQuad ( cayley . Quad ( vulnerability . Node , FieldVulnerabilityID , vulnerability . ID , "" ) )
t . AddQuad ( cayley . Quad ( vulnerability . Node , FieldVulnerabilityID , vulnerability . ID , "" ) )
@ -177,7 +160,11 @@ func InsertVulnerabilities(vulnerabilities []*Vulnerability) ([]Notification, er
}
}
// Add a notification
// Add a notification
newVulnerabilityNotifications [ vulnerability . ID ] = & NewVulnerabilityNotification { VulnerabilityID : vulnerability . ID }
notification := & NewVulnerabilityNotification { VulnerabilityID : vulnerability . ID }
notifications = append ( notifications , notification )
newVulnerabilityNotifications [ vulnerability . ID ] = notification
cachedVulnerabilities [ vulnerability . ID ] = vulnerability
} else {
} else {
// The vulnerability already exists, update it
// The vulnerability already exists, update it
if vulnerability . Link != "" && existingVulnerability . Link != vulnerability . Link {
if vulnerability . Link != "" && existingVulnerability . Link != vulnerability . Link {
@ -185,6 +172,7 @@ func InsertVulnerabilities(vulnerabilities []*Vulnerability) ([]Notification, er
t . AddQuad ( cayley . Quad ( existingVulnerability . Node , FieldVulnerabilityLink , vulnerability . Link , "" ) )
t . AddQuad ( cayley . Quad ( existingVulnerability . Node , FieldVulnerabilityLink , vulnerability . Link , "" ) )
existingVulnerability . Link = vulnerability . Link
existingVulnerability . Link = vulnerability . Link
}
}
if vulnerability . Priority != "" && vulnerability . Priority != types . Unknown && existingVulnerability . Priority != vulnerability . Priority {
if vulnerability . Priority != "" && vulnerability . Priority != types . Unknown && existingVulnerability . Priority != vulnerability . Priority {
if ! vulnerability . Priority . IsValid ( ) {
if ! vulnerability . Priority . IsValid ( ) {
log . Warningf ( "could not update a vulnerability which has an invalid priority [ID: %s, Link: %s, Priority: %s]. Valid priorities are: %v." , vulnerability . ID , vulnerability . Link , vulnerability . Priority , types . Priorities )
log . Warningf ( "could not update a vulnerability which has an invalid priority [ID: %s, Link: %s, Priority: %s]. Valid priorities are: %v." , vulnerability . ID , vulnerability . Link , vulnerability . Priority , types . Priorities )
@ -197,10 +185,12 @@ func InsertVulnerabilities(vulnerabilities []*Vulnerability) ([]Notification, er
// Any priorityChangeNotification already ?
// Any priorityChangeNotification already ?
if existingPriorityNotification , _ := vulnerabilityPriorityIncreasedNotifications [ vulnerability . ID ] ; existingPriorityNotification != nil {
if existingPriorityNotification , _ := vulnerabilityPriorityIncreasedNotifications [ vulnerability . ID ] ; existingPriorityNotification != nil {
// There is a priority change notification, replace it but keep the old priority field
// There is a priority change notification, replace it but keep the old priority field
vulnerabilityPriorityIncreasedNotifications[ vulnerability . ID ] = & VulnerabilityPriorityIncreasedNotification { OldPriority : existingPriorityNotification . OldPriority , NewPriority : vulnerability . Priority , VulnerabilityID : existingVulnerability . ID }
existingPriorityNotification. NewPriority = vulnerability . Priority
} else {
} else {
// No previous notification, just add a new one
// No previous notification, just add a new one
vulnerabilityPriorityIncreasedNotifications [ vulnerability . ID ] = & VulnerabilityPriorityIncreasedNotification { OldPriority : existingVulnerability . Priority , NewPriority : vulnerability . Priority , VulnerabilityID : existingVulnerability . ID }
notification := & VulnerabilityPriorityIncreasedNotification { OldPriority : existingVulnerability . Priority , NewPriority : vulnerability . Priority , VulnerabilityID : existingVulnerability . ID }
notifications = append ( notifications , notification )
vulnerabilityPriorityIncreasedNotifications [ vulnerability . ID ] = notification
}
}
}
}
}
}
@ -209,12 +199,15 @@ func InsertVulnerabilities(vulnerabilities []*Vulnerability) ([]Notification, er
t . AddQuad ( cayley . Quad ( existingVulnerability . Node , FieldVulnerabilityPriority , string ( vulnerability . Priority ) , "" ) )
t . AddQuad ( cayley . Quad ( existingVulnerability . Node , FieldVulnerabilityPriority , string ( vulnerability . Priority ) , "" ) )
existingVulnerability . Priority = vulnerability . Priority
existingVulnerability . Priority = vulnerability . Priority
}
}
if vulnerability . Description != "" && existingVulnerability . Description != vulnerability . Description {
if vulnerability . Description != "" && existingVulnerability . Description != vulnerability . Description {
t . RemoveQuad ( cayley . Quad ( existingVulnerability . Node , FieldVulnerabilityDescription , existingVulnerability . Description , "" ) )
t . RemoveQuad ( cayley . Quad ( existingVulnerability . Node , FieldVulnerabilityDescription , existingVulnerability . Description , "" ) )
t . AddQuad ( cayley . Quad ( existingVulnerability . Node , FieldVulnerabilityDescription , vulnerability . Description , "" ) )
t . AddQuad ( cayley . Quad ( existingVulnerability . Node , FieldVulnerabilityDescription , vulnerability . Description , "" ) )
existingVulnerability . Description = vulnerability . Description
existingVulnerability . Description = vulnerability . Description
}
}
if len ( vulnerability . FixedInNodes ) > 0 && len ( utils . CompareStringLists ( vulnerability . FixedInNodes , existingVulnerability . FixedInNodes ) ) != 0 {
newFixedInNodes := utils . CompareStringLists ( vulnerability . FixedInNodes , existingVulnerability . FixedInNodes )
if len ( newFixedInNodes ) > 0 {
var removedNodes [ ] string
var removedNodes [ ] string
var addedNodes [ ] string
var addedNodes [ ] string
@ -222,19 +215,14 @@ func InsertVulnerabilities(vulnerabilities []*Vulnerability) ([]Notification, er
if err != nil {
if err != nil {
return [ ] Notification { } , err
return [ ] Notification { } , err
}
}
vulnerabilityFixedInPackages, err := FindAllPackagesByNodes ( vulnerability . FixedInNodes, [ ] string { FieldPackageOS , FieldPackageName , FieldPackageVersion } )
newFixedInPackages, err := FindAllPackagesByNodes ( new FixedInNodes, [ ] string { FieldPackageOS , FieldPackageName , FieldPackageVersion } )
if err != nil {
if err != nil {
return [ ] Notification { } , err
return [ ] Notification { } , err
}
}
for _ , p := range vulnerabilityFixedInPackages {
for _ , p := range newFixedInPackages {
// Any already existing link ?
fixedInLinkAlreadyExists := false
for _ , ep := range existingVulnerabilityFixedInPackages {
for _ , ep := range existingVulnerabilityFixedInPackages {
if * p == * ep {
if p . Branch ( ) == ep . Branch ( ) {
// This exact link already exists, we won't insert it again
fixedInLinkAlreadyExists = true
} else if p . Branch ( ) == ep . Branch ( ) {
// A link to this package branch already exist and is not the same version, we will delete it
// A link to this package branch already exist and is not the same version, we will delete it
t . RemoveQuad ( cayley . Quad ( existingVulnerability . Node , FieldVulnerabilityFixedIn , ep . Node , "" ) )
t . RemoveQuad ( cayley . Quad ( existingVulnerability . Node , FieldVulnerabilityFixedIn , ep . Node , "" ) )
@ -250,15 +238,12 @@ func InsertVulnerabilities(vulnerabilities []*Vulnerability) ([]Notification, er
}
}
}
}
if fixedInLinkAlreadyExists == false {
t . AddQuad ( cayley . Quad ( existingVulnerability . Node , FieldVulnerabilityFixedIn , p . Node , "" ) )
t . AddQuad ( cayley . Quad ( existingVulnerability . Node , FieldVulnerabilityFixedIn , p . Node , "" ) )
existingVulnerability . FixedInNodes = append ( existingVulnerability . FixedInNodes , p . Node )
existingVulnerability . FixedInNodes = append ( existingVulnerability . FixedInNodes , p . Node )
addedNodes = append ( addedNodes , p . Node )
addedNodes = append ( addedNodes , p . Node )
}
}
}
// Add notification about the FixedIn modification if the vulnerability is not new
// Add notification about the FixedIn modification if the vulnerability is not new
if len ( removedNodes ) > 0 || len ( addedNodes ) > 0 {
if _ , newVulnerabilityNotificationExists := newVulnerabilityNotifications [ vulnerability . ID ] ; ! newVulnerabilityNotificationExists {
if _ , newVulnerabilityNotificationExists := newVulnerabilityNotifications [ vulnerability . ID ] ; ! newVulnerabilityNotificationExists {
// Any VulnerabilityPackageChangedNotification already ?
// Any VulnerabilityPackageChangedNotification already ?
if existingPackageNotification , _ := vulnerabilityPackageChangedNotifications [ vulnerability . ID ] ; existingPackageNotification != nil {
if existingPackageNotification , _ := vulnerabilityPackageChangedNotifications [ vulnerability . ID ] ; existingPackageNotification != nil {
@ -267,8 +252,9 @@ func InsertVulnerabilities(vulnerabilities []*Vulnerability) ([]Notification, er
existingPackageNotification . RemovedFixedInNodes = append ( existingPackageNotification . RemovedFixedInNodes , removedNodes ... )
existingPackageNotification . RemovedFixedInNodes = append ( existingPackageNotification . RemovedFixedInNodes , removedNodes ... )
} else {
} else {
// No previous notification, just add a new one
// No previous notification, just add a new one
vulnerabilityPackageChangedNotifications [ vulnerability . ID ] = & VulnerabilityPackageChangedNotification { VulnerabilityID : vulnerability . ID , AddedFixedInNodes : addedNodes , RemovedFixedInNodes : removedNodes }
notification := & VulnerabilityPackageChangedNotification { VulnerabilityID : vulnerability . ID , AddedFixedInNodes : addedNodes , RemovedFixedInNodes : removedNodes }
}
notifications = append ( notifications , notification )
vulnerabilityPackageChangedNotifications [ vulnerability . ID ] = notification
}
}
}
}
}
}
@ -281,19 +267,7 @@ func InsertVulnerabilities(vulnerabilities []*Vulnerability) ([]Notification, er
return [ ] Notification { } , ErrTransaction
return [ ] Notification { } , ErrTransaction
}
}
// Group all notifications
return notifications , nil
var allNotifications [ ] Notification
for _ , notification := range newVulnerabilityNotifications {
allNotifications = append ( allNotifications , notification )
}
for _ , notification := range vulnerabilityPriorityIncreasedNotifications {
allNotifications = append ( allNotifications , notification )
}
for _ , notification := range vulnerabilityPackageChangedNotifications {
allNotifications = append ( allNotifications , notification )
}
return allNotifications , nil
}
}
// DeleteVulnerability deletes the vulnerability having the given ID
// DeleteVulnerability deletes the vulnerability having the given ID