diff --git a/grafeas/grafeas.go b/grafeas/grafeas.go index fb151b5f..889a9232 100644 --- a/grafeas/grafeas.go +++ b/grafeas/grafeas.go @@ -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{}, + }, }, } }