Create grafeas project before writing vulnerabilities.

This commit is contained in:
Tobias Furuholm 2018-01-17 13:10:34 +01:00
parent 8397359296
commit 7a2ae81363

View File

@ -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{
CpeUri: cpeUri,
Package_: pkg,
Version: version,
return &pb.VulnerabilityType_VulnerabilityLocation{
CpeUri: cpeUri,
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{
CvssScore: score,
Severity: severity,
Details: []v1alpha1.Detail{},
Kind: pb.Note_PACKAGE_VULNERABILITY,
NoteType: &pb.Note_VulnerabilityType{
&pb.VulnerabilityType{
CvssScore: score,
Severity: severity,
Details: []*pb.VulnerabilityType_Detail{},
},
},
}
}