Skip to content

Commit

Permalink
Feature/arango neighbors verbs with tests (#1420)
Browse files Browse the repository at this point in the history
* add certifyBad neighbor query

Signed-off-by: pxp928 <[email protected]>

* add certifygood neighbor query

Signed-off-by: pxp928 <[email protected]>

* fix certifyGood unit test for neighbor

Signed-off-by: pxp928 <[email protected]>

* add certifyLegal, scorecard and vex neighbor queries

Signed-off-by: pxp928 <[email protected]>

* add certifyvuln, hashEqual and hasMetadata neighbor queries

Signed-off-by: pxp928 <[email protected]>

* add hasSBOM and hasSLSA neighbor queries

Signed-off-by: pxp928 <[email protected]>

* add hasSourceAt, isDep, isOcur neighbor queries

Signed-off-by: pxp928 <[email protected]>

* add pkgEqual, pointOfContact, vulnEqual, vulnMetadata neighbor queries

Signed-off-by: pxp928 <[email protected]>

---------

Signed-off-by: pxp928 <[email protected]>
  • Loading branch information
pxp928 authored Oct 22, 2023
1 parent 7a4373b commit 2ad8e2b
Show file tree
Hide file tree
Showing 19 changed files with 1,540 additions and 18 deletions.
42 changes: 42 additions & 0 deletions pkg/assembler/backends/arangodb/certifyBad.go
Original file line number Diff line number Diff line change
Expand Up @@ -1085,3 +1085,45 @@ func (c *arangoClient) queryCertifyBadNodeByID(ctx context.Context, filter *mode
}
return certifyBad, nil
}

func (c *arangoClient) certifyBadNeighbors(ctx context.Context, nodeID string, allowedEdges edgeMap) ([]string, error) {
out := make([]string, 0, 1)

if allowedEdges[model.EdgeCertifyBadPackage] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyBadsStr, "certifyBad")
setCertifyBadMatchValues(arangoQueryBuilder, &model.CertifyBadSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyBad.packageID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyBadNeighbors - package")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
if allowedEdges[model.EdgeCertifyBadArtifact] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyBadsStr, "certifyBad")
setCertifyBadMatchValues(arangoQueryBuilder, &model.CertifyBadSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyBad.artifactID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyBadNeighbors - artifact")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
if allowedEdges[model.EdgeCertifyBadSource] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyBadsStr, "certifyBad")
setCertifyBadMatchValues(arangoQueryBuilder, &model.CertifyBadSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyBad.sourceID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyBadNeighbors - source")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
return out, nil
}
42 changes: 42 additions & 0 deletions pkg/assembler/backends/arangodb/certifyGood.go
Original file line number Diff line number Diff line change
Expand Up @@ -1098,3 +1098,45 @@ func (c *arangoClient) queryCertifyGoodNodeByID(ctx context.Context, filter *mod
}
return certifyGood, nil
}

func (c *arangoClient) certifyGoodNeighbors(ctx context.Context, nodeID string, allowedEdges edgeMap) ([]string, error) {
out := make([]string, 0, 1)

if allowedEdges[model.EdgeCertifyGoodPackage] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyGoodsStr, "certifyGood")
setCertifyGoodMatchValues(arangoQueryBuilder, &model.CertifyGoodSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyGood.packageID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyGoodNeighbors - package")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
if allowedEdges[model.EdgeCertifyGoodArtifact] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyGoodsStr, "certifyGood")
setCertifyGoodMatchValues(arangoQueryBuilder, &model.CertifyGoodSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyGood.artifactID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyGoodNeighbors - artifact")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
if allowedEdges[model.EdgeCertifyGoodSource] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyGoodsStr, "certifyGood")
setCertifyGoodMatchValues(arangoQueryBuilder, &model.CertifyGoodSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyGood.sourceID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyGoodNeighbors - source")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
return out, nil
}
74 changes: 74 additions & 0 deletions pkg/assembler/backends/arangodb/certifyLegal.go
Original file line number Diff line number Diff line change
Expand Up @@ -1023,3 +1023,77 @@ func (c *arangoClient) queryCertifyLegalNodeByID(ctx context.Context, filter *mo
}
return certifyLegal, nil
}

func (c *arangoClient) certifyLegalNeighbors(ctx context.Context, nodeID string, allowedEdges edgeMap) ([]string, error) {
out := make([]string, 0, 2)
if allowedEdges[model.EdgeCertifyLegalPackage] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyLegalsStr, "certifyLegal")
setCertifyLegalMatchValues(arangoQueryBuilder, &model.CertifyLegalSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyLegal.packageID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyLegalNeighbors - package")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
if allowedEdges[model.EdgeCertifyLegalSource] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyLegalsStr, "certifyLegal")
setCertifyLegalMatchValues(arangoQueryBuilder, &model.CertifyLegalSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyLegal.sourceID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyLegalNeighbors - source")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
if allowedEdges[model.EdgeCertifyLegalLicense] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyLegalsStr, "certifyLegal")
setCertifyLegalMatchValues(arangoQueryBuilder, &model.CertifyLegalSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { declared: certifyLegal.declaredLicenses, discovered: certifyLegal.discoveredLicenses }")

cursor, err := executeQueryWithRetry(ctx, c.db, arangoQueryBuilder.string(), values, "getNeighborIDFromCursor - certifyLegalNeighbors")
if err != nil {
return nil, fmt.Errorf("failed to query for Neighbors for %s with error: %w", "certifyLegalNeighbors", err)
}
defer cursor.Close()

type dbLicenseNeighbor struct {
Declared []string `json:"declared"`
Discovered []string `json:"discovered"`
}

var foundLicenseNeighbors []dbLicenseNeighbor
for {
var doc dbLicenseNeighbor
_, err := cursor.ReadDocument(ctx, &doc)
if err != nil {
if driver.IsNoMoreDocuments(err) {
break
} else {
return nil, fmt.Errorf("failed to get neighbor id from cursor for %s with error: %w", "certifyLegalNeighbors", err)
}
} else {
foundLicenseNeighbors = append(foundLicenseNeighbors, doc)
}
}

var foundIDs []string
for _, foundLicNeighbor := range foundLicenseNeighbors {
if foundLicNeighbor.Declared != nil {
foundIDs = append(foundIDs, foundLicNeighbor.Declared...)
}
if foundLicNeighbor.Discovered != nil {
foundIDs = append(foundIDs, foundLicNeighbor.Discovered...)
}
}

out = append(out, foundIDs...)
}

return out, nil
}
18 changes: 18 additions & 0 deletions pkg/assembler/backends/arangodb/certifyScorecard.go
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,21 @@ func (c *arangoClient) queryCertifyScorecardNodeByID(ctx context.Context, filter
Scorecard: scorecard,
}, nil
}

func (c *arangoClient) certifyScorecardNeighbors(ctx context.Context, nodeID string, allowedEdges edgeMap) ([]string, error) {
out := make([]string, 0, 1)
if allowedEdges[model.EdgeCertifyScorecardSource] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(scorecardStr, "scorecard")
setCertifyScorecardMatchValues(arangoQueryBuilder, &model.CertifyScorecardSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: scorecard.sourceID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyScorecardNeighbors - source")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}

return out, nil
}
42 changes: 42 additions & 0 deletions pkg/assembler/backends/arangodb/certifyVEXStatement.go
Original file line number Diff line number Diff line change
Expand Up @@ -854,3 +854,45 @@ func (c *arangoClient) queryCertifyVexNodeByID(ctx context.Context, filter *mode
}
return vex, nil
}

func (c *arangoClient) certifyVexNeighbors(ctx context.Context, nodeID string, allowedEdges edgeMap) ([]string, error) {
out := make([]string, 0, 2)
if allowedEdges[model.EdgeCertifyVexStatementPackage] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyVEXsStr, "certifyVex")
setVexMatchValues(arangoQueryBuilder, &model.CertifyVEXStatementSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyVex.packageID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyScorecardNeighbors - package")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
if allowedEdges[model.EdgeCertifyVexStatementArtifact] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyVEXsStr, "certifyVex")
setVexMatchValues(arangoQueryBuilder, &model.CertifyVEXStatementSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyVex.artifactID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyScorecardNeighbors - package")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
if allowedEdges[model.EdgeCertifyVexStatementVulnerability] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyVEXsStr, "certifyVex")
setVexMatchValues(arangoQueryBuilder, &model.CertifyVEXStatementSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyVex.vulnerabilityID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyScorecardNeighbors - package")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}

return out, nil
}
30 changes: 30 additions & 0 deletions pkg/assembler/backends/arangodb/certifyVuln.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,3 +576,33 @@ func (c *arangoClient) queryCertifyVulnNodeByID(ctx context.Context, filter *mod

return certifyVuln, nil
}

func (c *arangoClient) certifyVulnNeighbors(ctx context.Context, nodeID string, allowedEdges edgeMap) ([]string, error) {
out := make([]string, 0, 2)
if allowedEdges[model.EdgeCertifyVulnPackage] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyVulnsStr, "certifyVuln")
setCertifyVulnMatchValues(arangoQueryBuilder, &model.CertifyVulnSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyVuln.packageID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyVulnNeighbors - package")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
if allowedEdges[model.EdgeCertifyVulnVulnerability] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(certifyVulnsStr, "certifyVuln")
setCertifyVulnMatchValues(arangoQueryBuilder, &model.CertifyVulnSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: certifyVuln.vulnerabilityID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "certifyVulnNeighbors - vulnerability")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}

return out, nil
}
42 changes: 42 additions & 0 deletions pkg/assembler/backends/arangodb/hasMetadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -1155,3 +1155,45 @@ func (c *arangoClient) queryHasMetadataNodeByID(ctx context.Context, filter *mod
}
return hasMetadata, nil
}

func (c *arangoClient) hasMetadataNeighbors(ctx context.Context, nodeID string, allowedEdges edgeMap) ([]string, error) {
out := make([]string, 0, 1)
if allowedEdges[model.EdgeHasMetadataPackage] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(hasMetadataStr, "hasMetadata")
setHasMetadataMatchValues(arangoQueryBuilder, &model.HasMetadataSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: hasMetadata.packageID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "hasMetadataNeighbors - package")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
if allowedEdges[model.EdgeHasMetadataArtifact] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(hasMetadataStr, "hasMetadata")
setHasMetadataMatchValues(arangoQueryBuilder, &model.HasMetadataSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: hasMetadata.artifactID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "hasMetadataNeighbors - artifact")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
if allowedEdges[model.EdgeHasMetadataSource] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(hasMetadataStr, "hasMetadata")
setHasMetadataMatchValues(arangoQueryBuilder, &model.HasMetadataSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: hasMetadata.sourceID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "hasMetadataNeighbors - source")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}

return out, nil
}
31 changes: 31 additions & 0 deletions pkg/assembler/backends/arangodb/hasSBOM.go
Original file line number Diff line number Diff line change
Expand Up @@ -699,3 +699,34 @@ func (c *arangoClient) queryHasSbomNodeByID(ctx context.Context, filter *model.H
}
return hasSBOM, nil
}

func (c *arangoClient) hasSbomNeighbors(ctx context.Context, nodeID string, allowedEdges edgeMap) ([]string, error) {
out := make([]string, 0, 1)

if allowedEdges[model.EdgeHasSbomPackage] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(hasSBOMsStr, "hasSBOM")
setHasSBOMMatchValues(arangoQueryBuilder, &model.HasSBOMSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: hasSBOM.packageID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "hasSbomNeighbors - package")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}
if allowedEdges[model.EdgeHasSbomArtifact] {
values := map[string]any{}
arangoQueryBuilder := newForQuery(hasSBOMsStr, "hasSBOM")
setHasSBOMMatchValues(arangoQueryBuilder, &model.HasSBOMSpec{ID: &nodeID}, values)
arangoQueryBuilder.query.WriteString("\nRETURN { neighbor: hasSBOM.artifactID }")

foundIDs, err := c.getNeighborIDFromCursor(ctx, arangoQueryBuilder, values, "hasSbomNeighbors - artifact")
if err != nil {
return out, fmt.Errorf("failed to get neighbors for node ID: %s from arango cursor with error: %w", nodeID, err)
}
out = append(out, foundIDs...)
}

return out, nil
}
Loading

0 comments on commit 2ad8e2b

Please sign in to comment.