Skip to content

Commit

Permalink
Move validation checks into resolvers (#1210)
Browse files Browse the repository at this point in the history
Signed-off-by: mrizzi <mrizzi@redhat.com>
  • Loading branch information
mrizzi committed Aug 31, 2023
1 parent 86b2099 commit a72cbbc
Show file tree
Hide file tree
Showing 82 changed files with 3,102 additions and 737 deletions.
55 changes: 55 additions & 0 deletions internal/testing/testdata/models.go
Expand Up @@ -116,7 +116,62 @@ var P2out = &model.Package{
}},
}

var P4 = &model.PkgInputSpec{
Type: "conan",
Namespace: ptrfrom.String("openssl.org"),
Name: "openssl",
Version: ptrfrom.String("3.0.3"),
}

var CB1out = &model.CertifyBad{
Subject: S2out,
Justification: "test justification",
}

var CG1out = &model.CertifyGood{
Subject: P1out,
Justification: "test justification one",
}

var SC1out = &model.CertifyScorecard{
Source: S1out,
Scorecard: &model.Scorecard{
Checks: []*model.ScorecardCheck{},
Origin: "test origin",
},
}

var V1 = &model.VulnerabilityInputSpec{
Type: "OSV",
VulnerabilityID: "CVE-2014-8140",
}

var VEX1out = &model.CertifyVEXStatement{
ID: "1",
}

var C1 = &model.VulnerabilityInputSpec{
Type: "cve",
VulnerabilityID: "CVE-2019-13110",
}
var C1out = &model.VulnerabilityID{
VulnerabilityID: "cve-2019-13110",
}

var C2 = &model.VulnerabilityInputSpec{
Type: "cve",
VulnerabilityID: "CVE-2014-8139",
}
var C2out = &model.VulnerabilityID{
VulnerabilityID: "cve-2014-8139",
}

var B1 = &model.BuilderInputSpec{
URI: "asdf",
}

var O1 = &model.VulnerabilityInputSpec{
Type: "OSV",
VulnerabilityID: "CVE-2014-8140",
}
var MAll = model.MatchFlags{Pkg: model.PkgMatchTypeAllVersions}
4 changes: 0 additions & 4 deletions pkg/assembler/backends/arangodb/certifyScorecard.go
Expand Up @@ -173,10 +173,6 @@ func getScorecardValues(src *model.SourceInputSpec, scorecard *model.ScorecardIn
// Ingest Scorecards

func (c *arangoClient) IngestScorecards(ctx context.Context, sources []*model.SourceInputSpec, scorecards []*model.ScorecardInputSpec) ([]*model.CertifyScorecard, error) {
if len(sources) != len(scorecards) {
return nil, fmt.Errorf("uneven source and scorecards for ingestion")
}

var listOfValues []map[string]any

for i := range sources {
Expand Down
8 changes: 0 additions & 8 deletions pkg/assembler/backends/arangodb/certifyVuln.go
Expand Up @@ -174,14 +174,6 @@ func getCertifyVulnQueryValues(pkg *model.PkgInputSpec, vulnerability *model.Vul
}

func (c *arangoClient) IngestCertifyVulns(ctx context.Context, pkgs []*model.PkgInputSpec, vulnerabilities []*model.VulnerabilityInputSpec, certifyVulns []*model.ScanMetadataInput) ([]*model.CertifyVuln, error) {
// TODO (pxp928): move checks to resolver so all backends don't have to implement
if len(pkgs) != len(vulnerabilities) {
return nil, fmt.Errorf("uneven packages and vulnerabilities for ingestion")
}
if len(pkgs) != len(certifyVulns) {
return nil, fmt.Errorf("uneven packages and certifyVuln for ingestion")
}

var listOfValues []map[string]any

for i := range certifyVulns {
Expand Down
8 changes: 0 additions & 8 deletions pkg/assembler/backends/arangodb/hasSBOM.go
Expand Up @@ -207,10 +207,6 @@ func getHasSBOMQueryValues(pkg *model.PkgInputSpec, artifact *model.ArtifactInpu

func (c *arangoClient) IngestHasSBOMs(ctx context.Context, subjects model.PackageOrArtifactInputs, hasSBOMs []*model.HasSBOMInputSpec) ([]*model.HasSbom, error) {
if len(subjects.Packages) > 0 {
if len(subjects.Packages) != len(hasSBOMs) {
return nil, fmt.Errorf("uneven packages and hasSBOMs for ingestion")
}

var listOfValues []map[string]any

for i := range subjects.Packages {
Expand Down Expand Up @@ -315,10 +311,6 @@ func (c *arangoClient) IngestHasSBOMs(ctx context.Context, subjects model.Packag

} else if len(subjects.Artifacts) > 0 {

if len(subjects.Artifacts) != len(hasSBOMs) {
return nil, fmt.Errorf("uneven artifacts and hasSBOMs for ingestion")
}

var listOfValues []map[string]any

for i := range subjects.Artifacts {
Expand Down
10 changes: 0 additions & 10 deletions pkg/assembler/backends/arangodb/hasSLSA.go
Expand Up @@ -179,16 +179,6 @@ func getSLSAValues(subject model.ArtifactInputSpec, builtFrom []*model.Artifact,
}

func (c *arangoClient) IngestSLSAs(ctx context.Context, subjects []*model.ArtifactInputSpec, builtFromList [][]*model.ArtifactInputSpec, builtByList []*model.BuilderInputSpec, slsaList []*model.SLSAInputSpec) ([]*model.HasSlsa, error) {
if len(subjects) != len(slsaList) {
return nil, fmt.Errorf("uneven subjects and slsa attestation for ingestion")
}
if len(subjects) != len(builtFromList) {
return nil, fmt.Errorf("uneven subjects and built from artifact list for ingestion")
}
if len(subjects) != len(builtByList) {
return nil, fmt.Errorf("uneven subjects and built by for ingestion")
}

builtFromMap := map[string][]*model.Artifact{}
var listOfValues []map[string]any

Expand Down
9 changes: 0 additions & 9 deletions pkg/assembler/backends/arangodb/hashEqual.go
Expand Up @@ -26,9 +26,6 @@ import (
)

func (c *arangoClient) HashEqual(ctx context.Context, hashEqualSpec *model.HashEqualSpec) ([]*model.HashEqual, error) {
if hashEqualSpec.Artifacts != nil && len(hashEqualSpec.Artifacts) > 2 {
return nil, fmt.Errorf("cannot specify more than 2 artifacts in HashEquals")
}
values := map[string]any{}
if hashEqualSpec.Artifacts != nil {
if len(hashEqualSpec.Artifacts) == 1 {
Expand Down Expand Up @@ -167,12 +164,6 @@ func getHashEqualQueryValues(artifact *model.ArtifactInputSpec, equalArtifact *m
}

func (c *arangoClient) IngestHashEquals(ctx context.Context, artifacts []*model.ArtifactInputSpec, otherArtifacts []*model.ArtifactInputSpec, hashEquals []*model.HashEqualInputSpec) ([]*model.HashEqual, error) {
if len(artifacts) != len(otherArtifacts) {
return nil, fmt.Errorf("uneven artifacts and other artifacts for ingestion")
} else if len(artifacts) != len(hashEquals) {
return nil, fmt.Errorf("uneven artifacts and hashEquals for ingestion")
}

var listOfValues []map[string]any

for i := range artifacts {
Expand Down
5 changes: 0 additions & 5 deletions pkg/assembler/backends/arangodb/isDependency.go
Expand Up @@ -304,11 +304,6 @@ func getDependencyQueryValues(pkg *model.PkgInputSpec, depPkg *model.PkgInputSpe

func (c *arangoClient) IngestDependencies(ctx context.Context, pkgs []*model.PkgInputSpec, depPkgs []*model.PkgInputSpec, depPkgMatchType model.MatchFlags, dependencies []*model.IsDependencyInputSpec) ([]*model.IsDependency, error) {
// TODO(LUMJJB): handle pkgmatchtype
if len(pkgs) != len(depPkgs) {
return nil, fmt.Errorf("uneven packages and dependent packages for ingestion")
} else if len(pkgs) != len(dependencies) {
return nil, fmt.Errorf("uneven packages and isDependency for ingestion")
}

var listOfValues []map[string]any

Expand Down
12 changes: 0 additions & 12 deletions pkg/assembler/backends/arangodb/isOccurrence.go
Expand Up @@ -225,12 +225,6 @@ func getOccurrenceQueryValues(pkg *model.PkgInputSpec, src *model.SourceInputSpe

func (c *arangoClient) IngestOccurrences(ctx context.Context, subjects model.PackageOrSourceInputs, artifacts []*model.ArtifactInputSpec, occurrences []*model.IsOccurrenceInputSpec) ([]*model.IsOccurrence, error) {
if len(subjects.Packages) > 0 {
if len(subjects.Packages) != len(artifacts) {
return nil, fmt.Errorf("uneven packages and artifacts for ingestion")
} else if len(subjects.Packages) != len(occurrences) {
return nil, fmt.Errorf("uneven packages and occurrence for ingestion")
}

var listOfValues []map[string]any

for i := range subjects.Packages {
Expand Down Expand Up @@ -337,12 +331,6 @@ func (c *arangoClient) IngestOccurrences(ctx context.Context, subjects model.Pac
return isOccurrenceList, nil

} else if len(subjects.Sources) > 0 {
if len(subjects.Sources) != len(artifacts) {
return nil, fmt.Errorf("uneven sources and artifacts for ingestion")
} else if len(subjects.Sources) != len(occurrences) {
return nil, fmt.Errorf("uneven sources and occurrence for ingestion")
}

var listOfValues []map[string]any

for i := range subjects.Sources {
Expand Down
7 changes: 0 additions & 7 deletions pkg/assembler/backends/ent/backend/dependency.go
Expand Up @@ -61,13 +61,6 @@ func (b *EntBackend) IsDependency(ctx context.Context, spec *model.IsDependencyS
}

func (b *EntBackend) IngestDependencies(ctx context.Context, pkgs []*model.PkgInputSpec, depPkgs []*model.PkgInputSpec, depPkgMatchType model.MatchFlags, dependencies []*model.IsDependencyInputSpec) ([]*model.IsDependency, error) {
if len(pkgs) != len(depPkgs) {
return nil, Errorf("uneven packages and dependent packages for ingestion")
}
if len(pkgs) != len(dependencies) {
return nil, Errorf("uneven packages and dependencies nodes for ingestion")
}

// TODO: This looks like a good candidate for using BulkCreate()

var modelIsDependencies []*model.IsDependency
Expand Down
12 changes: 0 additions & 12 deletions pkg/assembler/backends/ent/backend/occurrence.go
Expand Up @@ -25,21 +25,12 @@ import (
"github.com/guacsec/guac/pkg/assembler/backends/ent/packageversion"
"github.com/guacsec/guac/pkg/assembler/backends/ent/predicate"
"github.com/guacsec/guac/pkg/assembler/backends/ent/sourcename"
"github.com/guacsec/guac/pkg/assembler/backends/helper"
"github.com/guacsec/guac/pkg/assembler/graphql/model"
"github.com/pkg/errors"
"github.com/vektah/gqlparser/v2/gqlerror"
)

func (b *EntBackend) IsOccurrence(ctx context.Context, query *model.IsOccurrenceSpec) ([]*model.IsOccurrence, error) {
funcName := "IsOccurrence"
if query != nil {
if err := helper.ValidatePackageOrSourceQueryFilter(query.Subject); err != nil {
return nil, gqlerror.Errorf("%v :: %v", funcName, err)
}
} else {
return nil, nil
}

predicates := []predicate.Occurrence{
optionalPredicate(query.ID, IDEQ),
Expand Down Expand Up @@ -118,9 +109,6 @@ func (b *EntBackend) IngestOccurrence(ctx context.Context,
spec model.IsOccurrenceInputSpec,
) (*model.IsOccurrence, error) {
funcName := "IngestOccurrence"
if err := helper.ValidatePackageOrSourceInput(&subject, "IngestOccurrence"); err != nil {
return nil, gqlerror.Errorf("%v :: %s", funcName, err)
}

recordID, err := WithinTX(ctx, b.client, func(ctx context.Context) (*int, error) {
tx := ent.TxFromContext(ctx)
Expand Down
40 changes: 0 additions & 40 deletions pkg/assembler/backends/ent/backend/occurrence_test.go
Expand Up @@ -502,46 +502,6 @@ func (s *Suite) TestOccurrence() {
},
},
},
{
Name: "Ingest without package",
InPkg: []*model.PkgInputSpec{},
InArt: []*model.ArtifactInputSpec{a1},
Calls: []call{
{
PkgSrc: model.PackageOrSourceInput{
Package: p1,
},
Artifact: a1,
Occurrence: &model.IsOccurrenceInputSpec{
Justification: "justification",
},
},
},
ExpIngestErr: true,
},
{
Name: "Query error",
InPkg: []*model.PkgInputSpec{p1},
InArt: []*model.ArtifactInputSpec{a1},
Calls: []call{
{
PkgSrc: model.PackageOrSourceInput{
Package: p1,
},
Artifact: a1,
Occurrence: &model.IsOccurrenceInputSpec{
Justification: "justification",
},
},
},
Query: &model.IsOccurrenceSpec{
Subject: &model.PackageOrSourceSpec{
Package: &model.PkgSpec{},
Source: &model.SourceSpec{},
},
},
ExpQueryErr: true,
},
{
Name: "Query bad ID",
InPkg: []*model.PkgInputSpec{p1},
Expand Down
4 changes: 0 additions & 4 deletions pkg/assembler/backends/ent/backend/sbom.go
Expand Up @@ -23,7 +23,6 @@ import (
"github.com/guacsec/guac/pkg/assembler/backends/ent"
"github.com/guacsec/guac/pkg/assembler/backends/ent/billofmaterials"
"github.com/guacsec/guac/pkg/assembler/backends/ent/predicate"
"github.com/guacsec/guac/pkg/assembler/backends/helper"
"github.com/guacsec/guac/pkg/assembler/graphql/model"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -70,9 +69,6 @@ func (b *EntBackend) HasSBOM(ctx context.Context, spec *model.HasSBOMSpec) ([]*m

func (b *EntBackend) IngestHasSbom(ctx context.Context, subject model.PackageOrArtifactInput, spec model.HasSBOMInputSpec) (*model.HasSbom, error) {
funcName := "IngestHasSbom"
if err := helper.ValidatePackageOrArtifactInput(&subject, "IngestHasSbom"); err != nil {
return nil, Errorf("%v :: %s", funcName, err)
}

sbomId, err := WithinTX(ctx, b.client, func(ctx context.Context) (*int, error) {
client := ent.TxFromContext(ctx)
Expand Down
17 changes: 0 additions & 17 deletions pkg/assembler/backends/ent/backend/sbom_test.go
Expand Up @@ -421,23 +421,6 @@ func (s *Suite) Test_HasSBOM() {
},
ExpIngestErr: true,
},
{
Name: "Ingest without two subjects",
InPkg: []*model.PkgInputSpec{p1},
InArt: []*model.ArtifactInputSpec{a1},
Calls: []call{
{
Sub: model.PackageOrArtifactInput{
Package: p1,
Artifact: a1,
},
Spec: &model.HasSBOMInputSpec{
DownloadLocation: "location one",
},
},
},
ExpIngestErr: true,
},
{
Name: "Query bad ID",
InPkg: []*model.PkgInputSpec{p1},
Expand Down
4 changes: 0 additions & 4 deletions pkg/assembler/backends/ent/backend/slsa.go
Expand Up @@ -68,10 +68,6 @@ func (b *EntBackend) HasSlsa(ctx context.Context, spec *model.HasSLSASpec) ([]*m
}

func (b *EntBackend) IngestSLSA(ctx context.Context, subject model.ArtifactInputSpec, builtFrom []*model.ArtifactInputSpec, builtBy model.BuilderInputSpec, slsa model.SLSAInputSpec) (*model.HasSlsa, error) {
if len(builtFrom) < 1 {
return nil, fmt.Errorf("must have at least 1 builtFrom")
}

att, err := WithinTX(ctx, b.client, func(ctx context.Context) (*ent.SLSAAttestation, error) {
return upsertSLSA(ctx, ent.TxFromContext(ctx), subject, builtFrom, builtBy, slsa)
})
Expand Down
6 changes: 0 additions & 6 deletions pkg/assembler/backends/ent/backend/source.go
Expand Up @@ -130,12 +130,6 @@ func upsertHasSourceAt(ctx context.Context, client *ent.Tx, pkg model.PkgInputSp
}

func (b *EntBackend) Sources(ctx context.Context, filter *model.SourceSpec) ([]*model.Source, error) {
if filter != nil && filter.Commit != nil && filter.Tag != nil {
if *filter.Commit != "" && *filter.Tag != "" {
return nil, Errorf("Passing both commit and tag selectors is an error")
}
}

records, err := b.client.SourceName.Query().
Where(sourceQuery(filter)).
Limit(MaxPageSize).
Expand Down
33 changes: 33 additions & 0 deletions pkg/assembler/backends/helper/validation.go
Expand Up @@ -16,6 +16,8 @@
package helper

import (
"strings"

"github.com/guacsec/guac/pkg/assembler/graphql/model"
"github.com/vektah/gqlparser/v2/gqlerror"
)
Expand Down Expand Up @@ -124,3 +126,34 @@ func ValidatePackageOrArtifactQueryFilter(subject *model.PackageOrArtifactSpec)
}
return nil
}

// ValidateVexInput
/*
For [status] “not_affected”, a VEX statement SHOULD provide a [justification].
If [justification] is not provided then [impact_statement] MUST be provided.
For [status] “affected”, MUST include one [action_statement]
*/
func ValidateVexInput(vexStatement model.VexStatementInputSpec) error {
if vexStatement.Status == model.VexStatusNotAffected && vexStatement.VexJustification == model.VexJustificationNotProvided && vexStatement.Statement == "" {
return gqlerror.Errorf("for [status] “not_affected”, if [justification] is not provided then [statement] MUST be provided")
} else if vexStatement.Status == model.VexStatusAffected && vexStatement.VexJustification == model.VexJustificationNotProvided && vexStatement.Statement == "" {
return gqlerror.Errorf("for [status] “affected”, MUST include one [statement]")
}
return nil
}

func ValidateVulnerabilityInputSpec(vulnerability model.VulnerabilityInputSpec) error {
if strings.ToLower(vulnerability.Type) == "novuln" {
return gqlerror.Errorf("%v type cannot be used for VEX", vulnerability.Type)
}
return nil
}

func ValidateVulnerabilitySpec(vulnerability model.VulnerabilitySpec) error {
if vulnerability.NoVuln != nil && !*vulnerability.NoVuln {
if vulnerability.Type != nil && strings.EqualFold(*vulnerability.Type, "novuln") {
return gqlerror.Errorf("novuln boolean set to false, cannot specify vulnerability type to be novuln")
}
}
return nil
}

0 comments on commit a72cbbc

Please sign in to comment.