Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENT] Implement deletion for certifyVuln, hasSBOM and hasSLSA #1982

Merged
merged 4 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions internal/testing/backend/certifyVuln_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/guacsec/guac/internal/testing/ptrfrom"
"github.com/guacsec/guac/internal/testing/testdata"
"github.com/guacsec/guac/pkg/assembler/graphql/model"
"github.com/stretchr/testify/assert"
)

var vmd1 = &model.ScanMetadata{
Expand Down Expand Up @@ -1514,3 +1515,131 @@ func TestIngestCertifyVulns(t *testing.T) {
})
}
}

func TestDeleteCertifyVuln(t *testing.T) {
ctx := context.Background()
b := setupTest(t)
type call struct {
Pkgs []*model.IDorPkgInput
Vulns []*model.IDorVulnerabilityInput
CertifyVulns []*model.ScanMetadataInput
}
tests := []struct {
InPkg []*model.PkgInputSpec
Name string
InVuln []*model.VulnerabilityInputSpec
Calls []call
ExpVuln []*model.CertifyVuln
Query *model.CertifyVulnSpec
ExpIngestErr bool
ExpQueryErr bool
}{
{
Name: "HappyPath",
InVuln: []*model.VulnerabilityInputSpec{testdata.C1, testdata.C2},
InPkg: []*model.PkgInputSpec{testdata.P1, testdata.P2},
Calls: []call{
{
Pkgs: []*model.IDorPkgInput{{PackageInput: testdata.P2}, {PackageInput: testdata.P1}},
Vulns: []*model.IDorVulnerabilityInput{{VulnerabilityInput: testdata.C1}, {VulnerabilityInput: testdata.C2}},
CertifyVulns: []*model.ScanMetadataInput{
{
Collector: "test collector",
Origin: "test origin",
ScannerVersion: "v1.0.0",
ScannerURI: "test scanner uri",
DbVersion: "2023.01.01",
DbURI: "test db uri",
TimeScanned: testdata.T1,
},
{
Collector: "test collector",
Origin: "test origin",
ScannerVersion: "v1.0.0",
ScannerURI: "test scanner uri",
DbVersion: "2023.01.01",
DbURI: "test db uri",
TimeScanned: testdata.T1,
},
},
},
},
Query: &model.CertifyVulnSpec{
Collector: ptrfrom.String("test collector"),
},
ExpVuln: []*model.CertifyVuln{
{
ID: "1",
Package: testdata.P2out,
Vulnerability: &model.Vulnerability{
Type: "cve",
VulnerabilityIDs: []*model.VulnerabilityID{testdata.C1out},
},
Metadata: vmd1,
},
{
ID: "10",
Package: testdata.P1out,
Vulnerability: &model.Vulnerability{
Type: "cve",
VulnerabilityIDs: []*model.VulnerabilityID{testdata.C2out},
},
Metadata: vmd1,
},
},
},
}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
for _, v := range test.InVuln {
if _, err := b.IngestVulnerability(ctx, model.IDorVulnerabilityInput{VulnerabilityInput: v}); err != nil {
t.Fatalf("Could not ingest vulnerabilities: %a", err)
}
}
for _, p := range test.InPkg {
if _, err := b.IngestPackage(ctx, model.IDorPkgInput{PackageInput: p}); err != nil {
t.Fatalf("Could not ingest packages: %v", err)
}
}
for _, o := range test.Calls {
_, err := b.IngestCertifyVulns(ctx, o.Pkgs, o.Vulns, o.CertifyVulns)
if (err != nil) != test.ExpIngestErr {
t.Fatalf("did not get expected ingest error, want: %v, got: %v", test.ExpIngestErr, err)
}
if err != nil {
return
}

}
got, err := b.CertifyVulnList(ctx, *test.Query, nil, nil)
if (err != nil) != test.ExpQueryErr {
t.Fatalf("did not get expected query error, want: %v, got: %v", test.ExpQueryErr, err)
}
if err != nil {
return
}
var returnedObjects []*model.CertifyVuln
if got != nil {
for _, obj := range got.Edges {
returnedObjects = append(returnedObjects, obj.Node)
}
}
if diff := cmp.Diff(test.ExpVuln, returnedObjects, commonOpts); diff != "" {
t.Errorf("Unexpected results. (-want +got):\n%s", diff)
}
deleted, err := b.Delete(ctx, returnedObjects[0].ID)
if err != nil {
t.Fatalf("did not get expected query error, want: %v, got: %v", test.ExpQueryErr, err)
}
assert.True(t, deleted)
secondGot, err := b.CertifyVulnList(ctx, *test.Query, nil, nil)
if (err != nil) != test.ExpQueryErr {
t.Fatalf("did not get expected query error, want: %v, got: %v", test.ExpQueryErr, err)
}
if err != nil {
return
}
assert.True(t, len(secondGot.Edges) == 1)
})
}
}
241 changes: 241 additions & 0 deletions internal/testing/backend/hasSBOM_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/guacsec/guac/internal/testing/ptrfrom"
"github.com/guacsec/guac/internal/testing/testdata"
"github.com/guacsec/guac/pkg/assembler/graphql/model"
"github.com/stretchr/testify/assert"
)

type testDependency struct {
Expand Down Expand Up @@ -3169,3 +3170,243 @@ func TestIngestHasSBOMs(t *testing.T) {
})
}
}

func TestDeleteHasSBOM(t *testing.T) {
ctx := context.Background()
b := setupTest(t)
type call struct {
Sub model.PackageOrArtifactInputs
HS []*model.HasSBOMInputSpec
Inc []*model.HasSBOMIncludesInputSpec
}
tests := []struct {
Name string
InPkg []*model.PkgInputSpec
InArt []*model.ArtifactInputSpec
PkgArt *model.PackageOrArtifactInputs
IsDeps []testDependency
IsOccs []testOccurrence
Calls []call
Query *model.HasSBOMSpec
ExpHS []*model.HasSbom
ExpIngestErr bool
ExpQueryErr bool
}{
{
Name: "Query on Package",
InPkg: []*model.PkgInputSpec{testdata.P2, testdata.P4},
InArt: []*model.ArtifactInputSpec{testdata.A1},
PkgArt: &model.PackageOrArtifactInputs{
Packages: []*model.IDorPkgInput{&model.IDorPkgInput{PackageInput: testdata.P2}, &model.IDorPkgInput{PackageInput: testdata.P4}},
Artifacts: []*model.IDorArtifactInput{{ArtifactInput: testdata.A1}},
},
IsDeps: []testDependency{{
pkg: testdata.P2,
depPkg: testdata.P4,
matchType: mSpecific,
isDep: &model.IsDependencyInputSpec{
Justification: "test justification",
},
}},
IsOccs: []testOccurrence{{
Subj: &model.PackageOrSourceInput{Package: &model.IDorPkgInput{PackageInput: testdata.P4}},
Art: testdata.A1,
isOcc: &model.IsOccurrenceInputSpec{Justification: "test justification"},
}},
Calls: []call{
{
Sub: model.PackageOrArtifactInputs{
Packages: []*model.IDorPkgInput{&model.IDorPkgInput{PackageInput: testdata.P2}, &model.IDorPkgInput{PackageInput: testdata.P4}},
},
HS: []*model.HasSBOMInputSpec{
{
URI: "test uri",
},
{
URI: "test uri",
},
},
},
{
Sub: model.PackageOrArtifactInputs{
Artifacts: []*model.IDorArtifactInput{{ArtifactInput: testdata.A1}},
},
HS: []*model.HasSBOMInputSpec{
{
URI: "test uri",
},
},
},
},
Query: &model.HasSBOMSpec{
Subject: &model.PackageOrArtifactSpec{
Package: &model.PkgSpec{
Version: ptrfrom.String("2.11.1"),
},
},
},
ExpHS: []*model.HasSbom{
{
Subject: testdata.P2out,
URI: "test uri",
IncludedSoftware: []model.PackageOrArtifact{testdata.P2out, testdata.P4out, testdata.A1out},
IncludedDependencies: []*model.IsDependency{{
Package: testdata.P2out,
DependencyPackage: testdata.P4out,
Justification: "test justification",
}},
IncludedOccurrences: []*model.IsOccurrence{{
Subject: testdata.P4out,
Artifact: testdata.A1out,
Justification: "test justification",
}},
},
},
},
{
Name: "Query on Artifact",
InPkg: []*model.PkgInputSpec{testdata.P1},
InArt: []*model.ArtifactInputSpec{testdata.A1, testdata.A2},
PkgArt: &model.PackageOrArtifactInputs{
Packages: []*model.IDorPkgInput{&model.IDorPkgInput{PackageInput: testdata.P1}},
Artifacts: []*model.IDorArtifactInput{{ArtifactInput: testdata.A1}, {ArtifactInput: testdata.A2}},
},
IsOccs: []testOccurrence{{
Subj: &model.PackageOrSourceInput{Package: &model.IDorPkgInput{PackageInput: testdata.P1}},
Art: testdata.A2,
isOcc: &model.IsOccurrenceInputSpec{Justification: "test justification"},
}},
Calls: []call{
{
Sub: model.PackageOrArtifactInputs{
Packages: []*model.IDorPkgInput{&model.IDorPkgInput{PackageInput: testdata.P1}},
},
HS: []*model.HasSBOMInputSpec{
{
URI: "test uri",
},
},
},
{
Sub: model.PackageOrArtifactInputs{
Artifacts: []*model.IDorArtifactInput{{ArtifactInput: testdata.A1}, {ArtifactInput: testdata.A2}},
},
HS: []*model.HasSBOMInputSpec{
{
URI: "test uri",
},
{
URI: "test uri",
},
},
},
},
Query: &model.HasSBOMSpec{
Subject: &model.PackageOrArtifactSpec{
Artifact: &model.ArtifactSpec{
Algorithm: ptrfrom.String("sha1"),
},
},
},
ExpHS: []*model.HasSbom{
{
Subject: testdata.A2out,
URI: "test uri",
IncludedSoftware: []model.PackageOrArtifact{testdata.P1out, testdata.A1out, testdata.A2out},
IncludedOccurrences: []*model.IsOccurrence{{
Subject: testdata.P1out,
Artifact: testdata.A2out,
Justification: "test justification",
}},
},
},
},
}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
for _, p := range test.InPkg {
if _, err := b.IngestPackage(ctx, model.IDorPkgInput{PackageInput: p}); err != nil {
t.Fatalf("Could not ingest package: %v", err)
}
}
for _, a := range test.InArt {
if _, err := b.IngestArtifact(ctx, &model.IDorArtifactInput{ArtifactInput: a}); err != nil {
t.Fatalf("Could not ingest artifact: %v", err)
}
}
includes := model.HasSBOMIncludesInputSpec{}
if test.PkgArt != nil {
if pkgs, err := b.IngestPackages(ctx, test.PkgArt.Packages); err != nil {
t.Fatalf("Could not ingest package: %v", err)
} else {
for _, pkg := range pkgs {
includes.Packages = append(includes.Packages, pkg.PackageVersionID)
}
}
if arts, err := b.IngestArtifacts(ctx, test.PkgArt.Artifacts); err != nil {
t.Fatalf("Could not ingest artifact: %v", err)
} else {
includes.Artifacts = append(includes.Artifacts, arts...)
}
}

for _, dep := range test.IsDeps {
if isDep, err := b.IngestDependency(ctx, model.IDorPkgInput{PackageInput: dep.pkg}, model.IDorPkgInput{PackageInput: dep.depPkg}, dep.matchType, *dep.isDep); err != nil {
t.Fatalf("Could not ingest dependency: %v", err)
} else {
includes.Dependencies = append(includes.Dependencies, isDep)
}
}

for _, occ := range test.IsOccs {
if isOcc, err := b.IngestOccurrence(ctx, *occ.Subj, model.IDorArtifactInput{ArtifactInput: occ.Art}, *occ.isOcc); err != nil {
t.Fatalf("Could not ingest occurrence: %v", err)
} else {
includes.Occurrences = append(includes.Occurrences, isOcc)
}
}
for _, o := range test.Calls {
var sbomIncludes []*model.HasSBOMIncludesInputSpec
for count := 0; count < len(o.HS); count++ {
sbomIncludes = append(sbomIncludes, &includes)
}
_, err := b.IngestHasSBOMs(ctx, o.Sub, o.HS, sbomIncludes)
if (err != nil) != test.ExpIngestErr {
t.Fatalf("did not get expected ingest error, want: %v, got: %v", test.ExpIngestErr, err)
}
if err != nil {
return
}
}
got, err := b.HasSBOMList(ctx, *test.Query, nil, nil)
if (err != nil) != test.ExpQueryErr {
t.Fatalf("did not get expected query error, want: %v, got: %v", test.ExpQueryErr, err)
}
if err != nil {
return
}
var returnedObjects []*model.HasSbom
if got != nil {
for _, obj := range got.Edges {
returnedObjects = append(returnedObjects, obj.Node)
}
}
if diff := cmp.Diff(test.ExpHS, returnedObjects, commonOpts); diff != "" {
t.Errorf("Unexpected results. (-want +got):\n%s", diff)
}
deleted, err := b.Delete(ctx, returnedObjects[0].ID)
if err != nil {
t.Fatalf("did not get expected query error, want: %v, got: %v", test.ExpQueryErr, err)
}
assert.True(t, deleted)
secondGot, err := b.HasSBOMList(ctx, *test.Query, nil, nil)
if (err != nil) != test.ExpQueryErr {
t.Fatalf("did not get expected query error, want: %v, got: %v", test.ExpQueryErr, err)
}
if err != nil {
return
}
assert.Nil(t, secondGot)
})
}
}
Loading
Loading