Create grafeas project before writing vulnerabilities.
This commit is contained in:
parent
8397359296
commit
7a2ae81363
@ -1,6 +1,7 @@
|
||||
package grafeas
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
@ -8,8 +9,10 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/clair/database"
|
||||
"github.com/grafeas/client-go/v1alpha1"
|
||||
"github.com/grafeas/grafeas/samples/server/go-server/api/server/name"
|
||||
pb "github.com/grafeas/grafeas/v1alpha1/proto"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@ -45,15 +48,39 @@ func (g *Grafeas) Export(datastore database.Datastore) error {
|
||||
}
|
||||
|
||||
pID := g.Config.ProjectId
|
||||
client := v1alpha1.NewGrafeasApiWithBasePath(g.Config.Addr)
|
||||
conn, err := grpc.Dial(g.Config.Addr, grpc.WithInsecure())
|
||||
defer conn.Close()
|
||||
context := context.Background()
|
||||
pClient := pb.NewGrafeasProjectsClient(conn)
|
||||
_, err = pClient.GetProject(context,
|
||||
&pb.GetProjectRequest{
|
||||
Name: fmt.Sprintf("projects/%s", pID),
|
||||
})
|
||||
if err != nil {
|
||||
// Project does not exist Create project
|
||||
log.Println("CreateProject")
|
||||
_, err = pClient.CreateProject(context,
|
||||
&pb.CreateProjectRequest{
|
||||
Name: fmt.Sprintf("projects/%s", pID),
|
||||
})
|
||||
if err != nil {
|
||||
// Failed to access API
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
client := pb.NewGrafeasClient(conn)
|
||||
for _, vuln := range vulnerabilities {
|
||||
nID := vuln.Name
|
||||
score, nistVectors := extractMetadata(vuln.Metadata)
|
||||
note, _, err := client.GetNote(pID, nID)
|
||||
note, err := client.GetNote(
|
||||
context,
|
||||
&pb.GetNoteRequest{
|
||||
Name: name.NoteName(pID, nID),
|
||||
})
|
||||
createNewNote := false
|
||||
if err != nil {
|
||||
n := noteWithoutDetails(pID, nID, vuln.Description, string(vuln.Severity), nistVectors, score)
|
||||
note = &n
|
||||
note = noteWithoutDetails(pID, nID, vuln.Description, nistVectors, score, severity(vuln.Severity))
|
||||
createNewNote = true
|
||||
}
|
||||
|
||||
@ -61,20 +88,29 @@ func (g *Grafeas) Export(datastore database.Datastore) error {
|
||||
for _, affected := range vuln.Affected {
|
||||
cpeUri := createCpeUri(affected.Namespace.Name)
|
||||
detail := detail(cpeUri, affected.FeatureName, vuln.Description, string(vuln.Severity), affected.FixedInVersion)
|
||||
index := findDetail(note.VulnerabilityType.Details, detail)
|
||||
index := findDetail(note.GetVulnerabilityType().Details, detail)
|
||||
if index == -1 {
|
||||
note.VulnerabilityType.Details = append(note.VulnerabilityType.Details, detail)
|
||||
note.GetVulnerabilityType().Details = append(note.GetVulnerabilityType().Details, &detail)
|
||||
containsUpdatedDetail = true
|
||||
} else if !reflect.DeepEqual(note.VulnerabilityType.Details[index], detail) {
|
||||
note.VulnerabilityType.Details[index] = detail
|
||||
} else if !reflect.DeepEqual(note.GetVulnerabilityType().Details[index], detail) {
|
||||
note.GetVulnerabilityType().Details[index] = &detail
|
||||
containsUpdatedDetail = true
|
||||
}
|
||||
}
|
||||
|
||||
if createNewNote {
|
||||
_, _, err = client.CreateNote(pID, nID, *note)
|
||||
_, err = client.CreateNote(context,
|
||||
&pb.CreateNoteRequest{
|
||||
Parent: fmt.Sprintf("projects/%s", pID),
|
||||
NoteId: nID,
|
||||
Note: note,
|
||||
})
|
||||
} else if containsUpdatedDetail {
|
||||
_, _, err = client.UpdateNote(pID, nID, *note)
|
||||
_, err = client.UpdateNote(context,
|
||||
&pb.UpdateNoteRequest{
|
||||
Name: name.NoteName(pID, nID),
|
||||
Note: note,
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -125,20 +161,39 @@ func createCpeUri(namespaceName string) string {
|
||||
return "CPE_UNSPECIFIED"
|
||||
}
|
||||
|
||||
func findDetail(details []v1alpha1.Detail, detail v1alpha1.Detail) int {
|
||||
func findDetail(details []*pb.VulnerabilityType_Detail, detail pb.VulnerabilityType_Detail) int {
|
||||
for i, d := range details {
|
||||
if d.CpeUri == detail.CpeUri && d.Package_ == detail.Package_ {
|
||||
if d.CpeUri == detail.CpeUri && d.PackageType == detail.PackageType {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func fixedLocation(fixedBy, cpeUri, pkg string) v1alpha1.VulnerabilityLocation {
|
||||
var version v1alpha1.Version
|
||||
func severity(severity database.Severity) pb.VulnerabilityType_Severity {
|
||||
switch severity {
|
||||
case database.Defcon1Severity:
|
||||
return pb.VulnerabilityType_CRITICAL
|
||||
case database.CriticalSeverity:
|
||||
return pb.VulnerabilityType_CRITICAL
|
||||
case database.HighSeverity:
|
||||
return pb.VulnerabilityType_HIGH
|
||||
case database.MediumSeverity:
|
||||
return pb.VulnerabilityType_MEDIUM
|
||||
case database.LowSeverity:
|
||||
return pb.VulnerabilityType_LOW
|
||||
case database.NegligibleSeverity:
|
||||
return pb.VulnerabilityType_LOW
|
||||
default:
|
||||
return pb.VulnerabilityType_SEVERITY_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
func fixedLocation(fixedBy, cpeUri, pkg string) *pb.VulnerabilityType_VulnerabilityLocation {
|
||||
var version pb.VulnerabilityType_Version
|
||||
if fixedBy == "" {
|
||||
version = v1alpha1.Version{
|
||||
Kind: "MAXIMUM",
|
||||
version = pb.VulnerabilityType_Version{
|
||||
Kind: pb.VulnerabilityType_Version_MAXIMUM,
|
||||
}
|
||||
} else {
|
||||
// EVR: Epoch:Version.Revision
|
||||
@ -148,51 +203,53 @@ func fixedLocation(fixedBy, cpeUri, pkg string) v1alpha1.VulnerabilityLocation {
|
||||
versionEpoch, _ := strconv.ParseInt(matches[1], 10, 32)
|
||||
versionName := matches[2]
|
||||
versionRev := matches[3]
|
||||
version = v1alpha1.Version{
|
||||
version = pb.VulnerabilityType_Version{
|
||||
Epoch: int32(versionEpoch),
|
||||
Name: versionName,
|
||||
Revision: versionRev,
|
||||
}
|
||||
} else {
|
||||
version = v1alpha1.Version{
|
||||
version = pb.VulnerabilityType_Version{
|
||||
Name: fixedBy,
|
||||
}
|
||||
}
|
||||
}
|
||||
return v1alpha1.VulnerabilityLocation{
|
||||
return &pb.VulnerabilityType_VulnerabilityLocation{
|
||||
CpeUri: cpeUri,
|
||||
Package_: pkg,
|
||||
Version: version,
|
||||
Package: pkg,
|
||||
Version: &version,
|
||||
}
|
||||
}
|
||||
|
||||
func detail(cpeUri, packageName, description, severity, fixedBy string) v1alpha1.Detail {
|
||||
return v1alpha1.Detail{
|
||||
func detail(cpeUri, packageName, description, severity, fixedBy string) pb.VulnerabilityType_Detail {
|
||||
return pb.VulnerabilityType_Detail{
|
||||
CpeUri: cpeUri,
|
||||
Package_: packageName,
|
||||
Package: packageName,
|
||||
Description: description,
|
||||
MinAffectedVersion: v1alpha1.Version{
|
||||
Kind: "MINIMUM",
|
||||
MinAffectedVersion: &pb.VulnerabilityType_Version{
|
||||
Kind: pb.VulnerabilityType_Version_MINIMUM,
|
||||
},
|
||||
SeverityName: severity,
|
||||
FixedLocation: fixedLocation(fixedBy, cpeUri, packageName),
|
||||
}
|
||||
}
|
||||
|
||||
func noteWithoutDetails(pID, name, description, severity, nistVectors string, score float32) v1alpha1.Note {
|
||||
func noteWithoutDetails(pID, name, description, nistVectors string, score float32, severity pb.VulnerabilityType_Severity) *pb.Note {
|
||||
var longDescription string
|
||||
if nistVectors != "" {
|
||||
longDescription = fmt.Sprintf("NIST vectors: %v", nistVectors)
|
||||
}
|
||||
return v1alpha1.Note{
|
||||
return &pb.Note{
|
||||
Name: fmt.Sprintf("projects/%v/notes/%v", pID, name),
|
||||
ShortDescription: name,
|
||||
LongDescription: longDescription,
|
||||
Kind: "PACKAGE_VULNERABILITY",
|
||||
VulnerabilityType: v1alpha1.VulnerabilityType{
|
||||
Kind: pb.Note_PACKAGE_VULNERABILITY,
|
||||
NoteType: &pb.Note_VulnerabilityType{
|
||||
&pb.VulnerabilityType{
|
||||
CvssScore: score,
|
||||
Severity: severity,
|
||||
Details: []v1alpha1.Detail{},
|
||||
Details: []*pb.VulnerabilityType_Detail{},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user