Create grafeas project before writing vulnerabilities.
This commit is contained in:
parent
8397359296
commit
7a2ae81363
@ -1,6 +1,7 @@
|
|||||||
package grafeas
|
package grafeas
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -8,8 +9,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/coreos/clair/database"
|
"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"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@ -45,15 +48,39 @@ func (g *Grafeas) Export(datastore database.Datastore) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pID := g.Config.ProjectId
|
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 {
|
for _, vuln := range vulnerabilities {
|
||||||
nID := vuln.Name
|
nID := vuln.Name
|
||||||
score, nistVectors := extractMetadata(vuln.Metadata)
|
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
|
createNewNote := false
|
||||||
if err != nil {
|
if err != nil {
|
||||||
n := noteWithoutDetails(pID, nID, vuln.Description, string(vuln.Severity), nistVectors, score)
|
note = noteWithoutDetails(pID, nID, vuln.Description, nistVectors, score, severity(vuln.Severity))
|
||||||
note = &n
|
|
||||||
createNewNote = true
|
createNewNote = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,20 +88,29 @@ func (g *Grafeas) Export(datastore database.Datastore) error {
|
|||||||
for _, affected := range vuln.Affected {
|
for _, affected := range vuln.Affected {
|
||||||
cpeUri := createCpeUri(affected.Namespace.Name)
|
cpeUri := createCpeUri(affected.Namespace.Name)
|
||||||
detail := detail(cpeUri, affected.FeatureName, vuln.Description, string(vuln.Severity), affected.FixedInVersion)
|
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 {
|
if index == -1 {
|
||||||
note.VulnerabilityType.Details = append(note.VulnerabilityType.Details, detail)
|
note.GetVulnerabilityType().Details = append(note.GetVulnerabilityType().Details, &detail)
|
||||||
containsUpdatedDetail = true
|
containsUpdatedDetail = true
|
||||||
} else if !reflect.DeepEqual(note.VulnerabilityType.Details[index], detail) {
|
} else if !reflect.DeepEqual(note.GetVulnerabilityType().Details[index], detail) {
|
||||||
note.VulnerabilityType.Details[index] = detail
|
note.GetVulnerabilityType().Details[index] = &detail
|
||||||
containsUpdatedDetail = true
|
containsUpdatedDetail = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if createNewNote {
|
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 {
|
} 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 {
|
if err != nil {
|
||||||
@ -125,20 +161,39 @@ func createCpeUri(namespaceName string) string {
|
|||||||
return "CPE_UNSPECIFIED"
|
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 {
|
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 i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func fixedLocation(fixedBy, cpeUri, pkg string) v1alpha1.VulnerabilityLocation {
|
func severity(severity database.Severity) pb.VulnerabilityType_Severity {
|
||||||
var version v1alpha1.Version
|
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 == "" {
|
if fixedBy == "" {
|
||||||
version = v1alpha1.Version{
|
version = pb.VulnerabilityType_Version{
|
||||||
Kind: "MAXIMUM",
|
Kind: pb.VulnerabilityType_Version_MAXIMUM,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// EVR: Epoch:Version.Revision
|
// EVR: Epoch:Version.Revision
|
||||||
@ -148,51 +203,53 @@ func fixedLocation(fixedBy, cpeUri, pkg string) v1alpha1.VulnerabilityLocation {
|
|||||||
versionEpoch, _ := strconv.ParseInt(matches[1], 10, 32)
|
versionEpoch, _ := strconv.ParseInt(matches[1], 10, 32)
|
||||||
versionName := matches[2]
|
versionName := matches[2]
|
||||||
versionRev := matches[3]
|
versionRev := matches[3]
|
||||||
version = v1alpha1.Version{
|
version = pb.VulnerabilityType_Version{
|
||||||
Epoch: int32(versionEpoch),
|
Epoch: int32(versionEpoch),
|
||||||
Name: versionName,
|
Name: versionName,
|
||||||
Revision: versionRev,
|
Revision: versionRev,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
version = v1alpha1.Version{
|
version = pb.VulnerabilityType_Version{
|
||||||
Name: fixedBy,
|
Name: fixedBy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return v1alpha1.VulnerabilityLocation{
|
return &pb.VulnerabilityType_VulnerabilityLocation{
|
||||||
CpeUri: cpeUri,
|
CpeUri: cpeUri,
|
||||||
Package_: pkg,
|
Package: pkg,
|
||||||
Version: version,
|
Version: &version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func detail(cpeUri, packageName, description, severity, fixedBy string) v1alpha1.Detail {
|
func detail(cpeUri, packageName, description, severity, fixedBy string) pb.VulnerabilityType_Detail {
|
||||||
return v1alpha1.Detail{
|
return pb.VulnerabilityType_Detail{
|
||||||
CpeUri: cpeUri,
|
CpeUri: cpeUri,
|
||||||
Package_: packageName,
|
Package: packageName,
|
||||||
Description: description,
|
Description: description,
|
||||||
MinAffectedVersion: v1alpha1.Version{
|
MinAffectedVersion: &pb.VulnerabilityType_Version{
|
||||||
Kind: "MINIMUM",
|
Kind: pb.VulnerabilityType_Version_MINIMUM,
|
||||||
},
|
},
|
||||||
SeverityName: severity,
|
SeverityName: severity,
|
||||||
FixedLocation: fixedLocation(fixedBy, cpeUri, packageName),
|
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
|
var longDescription string
|
||||||
if nistVectors != "" {
|
if nistVectors != "" {
|
||||||
longDescription = fmt.Sprintf("NIST vectors: %v", nistVectors)
|
longDescription = fmt.Sprintf("NIST vectors: %v", nistVectors)
|
||||||
}
|
}
|
||||||
return v1alpha1.Note{
|
return &pb.Note{
|
||||||
Name: fmt.Sprintf("projects/%v/notes/%v", pID, name),
|
Name: fmt.Sprintf("projects/%v/notes/%v", pID, name),
|
||||||
ShortDescription: name,
|
ShortDescription: name,
|
||||||
LongDescription: longDescription,
|
LongDescription: longDescription,
|
||||||
Kind: "PACKAGE_VULNERABILITY",
|
Kind: pb.Note_PACKAGE_VULNERABILITY,
|
||||||
VulnerabilityType: v1alpha1.VulnerabilityType{
|
NoteType: &pb.Note_VulnerabilityType{
|
||||||
CvssScore: score,
|
&pb.VulnerabilityType{
|
||||||
Severity: severity,
|
CvssScore: score,
|
||||||
Details: []v1alpha1.Detail{},
|
Severity: severity,
|
||||||
|
Details: []*pb.VulnerabilityType_Detail{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user