Skip to content

Commit

Permalink
Merge branch 'main' into feat/snyk-enrich-external-refs
Browse files Browse the repository at this point in the history
  • Loading branch information
paulrosca-snyk committed Mar 4, 2024
2 parents b409492 + 6bf7ae4 commit a5f2a63
Show file tree
Hide file tree
Showing 21 changed files with 129 additions and 87 deletions.
8 changes: 4 additions & 4 deletions internal/commands/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ func NewDefaultCommand() *cobra.Command {

cmd.SetVersionTemplate(`{{.Version}}`)

cmd.AddCommand(ecosystems.NewEcosystemsRootCommand(logger))
cmd.AddCommand(snyk.NewSnykRootCommand(logger))
cmd.AddCommand(deps.NewDepsRootCommand(logger))
cmd.AddCommand(scorecard.NewRootCommand(logger))
cmd.AddCommand(ecosystems.NewEcosystemsRootCommand(&logger))
cmd.AddCommand(snyk.NewSnykRootCommand(&logger))
cmd.AddCommand(deps.NewDepsRootCommand(&logger))
cmd.AddCommand(scorecard.NewRootCommand(&logger))

return &cmd
}
Expand Down
8 changes: 5 additions & 3 deletions internal/commands/deps/repos.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,22 @@ import (
"github.com/snyk/parlay/lib/deps"
)

func NewRepoCommand(logger zerolog.Logger) *cobra.Command {
func NewRepoCommand(logger *zerolog.Logger) *cobra.Command {
cmd := cobra.Command{
Use: "repo <repo>",
Short: "Return repo info from deps.dev",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
repo, err := deps.GetRepoData(args[0])
if err != nil {
logger.Fatal().Err(err).Msg("Error retrieving data from deps.dev")
logger.Fatal().Err(err).Msg("Failed to retrieve data from deps.dev")
}

repository, err := json.Marshal(repo)
if err != nil {
logger.Fatal().Err(err).Msg("Error with JSON response from deps.dev")
logger.Fatal().Err(err).Msg("Failed to parse response from deps.dev")
}

fmt.Print(string(repository))
},
}
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/deps/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"github.com/spf13/cobra"
)

func NewDepsRootCommand(logger zerolog.Logger) *cobra.Command {
func NewDepsRootCommand(logger *zerolog.Logger) *cobra.Command {
cmd := cobra.Command{
Use: "deps",
Short: "Commands for using parlay with deps.dev",
Expand Down
6 changes: 3 additions & 3 deletions internal/commands/ecosystems/enrich.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,23 @@ import (
"github.com/snyk/parlay/lib/sbom"
)

func NewEnrichCommand(logger zerolog.Logger) *cobra.Command {
func NewEnrichCommand(logger *zerolog.Logger) *cobra.Command {
cmd := cobra.Command{
Use: "enrich <sbom>",
Short: "Enrich an SBOM with ecosyste.ms data",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
b, err := utils.GetUserInput(args[0], os.Stdin)
if err != nil {
logger.Fatal().Err(err).Msg("Problem reading input")
logger.Fatal().Err(err).Msg("Failed to read input")
}

doc, err := sbom.DecodeSBOMDocument(b)
if err != nil {
logger.Fatal().Err(err).Msg("Failed to read SBOM input")
}

ecosystems.EnrichSBOM(doc)
ecosystems.EnrichSBOM(doc, logger)

if err := doc.Encode(os.Stdout); err != nil {
logger.Fatal().Err(err).Msg("Failed to encode new SBOM")
Expand Down
10 changes: 6 additions & 4 deletions internal/commands/ecosystems/packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,22 @@ import (
"github.com/snyk/parlay/lib/ecosystems"
)

func NewPackageCommand(logger zerolog.Logger) *cobra.Command {
func NewPackageCommand(logger *zerolog.Logger) *cobra.Command {
cmd := cobra.Command{
Use: "package <purl> ",
Use: "package <purl>",
Short: "Return package info from ecosyste.ms",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
purl, err := packageurl.FromString(args[0])
if err != nil {
logger.Fatal().Err(err)
logger.Fatal().Err(err).Msg("Failed to parse PackageURL")
}

resp, err := ecosystems.GetPackageData(purl)
if err != nil {
logger.Fatal().Err(err)
logger.Fatal().Err(err).Msg("Failed to get package data from ecosyste.ms")
}

fmt.Print(string(resp.Body))
},
}
Expand Down
4 changes: 2 additions & 2 deletions internal/commands/ecosystems/repos.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import (
"github.com/snyk/parlay/lib/ecosystems"
)

func NewRepoCommand(logger zerolog.Logger) *cobra.Command {
func NewRepoCommand(logger *zerolog.Logger) *cobra.Command {
cmd := cobra.Command{
Use: "repo <host> <repo>",
Short: "Return repo info from ecosyste.ms",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
resp, err := ecosystems.GetRepoData(args[0])
if err != nil {
logger.Fatal().Err(err).Msg("An error occurred")
logger.Fatal().Err(err).Msg("Failed to get repository data from ecosyste.ms")
}
fmt.Print(string(resp.Body))
},
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/ecosystems/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"github.com/spf13/cobra"
)

func NewEcosystemsRootCommand(logger zerolog.Logger) *cobra.Command {
func NewEcosystemsRootCommand(logger *zerolog.Logger) *cobra.Command {
cmd := cobra.Command{
Use: "ecosystems",
Short: "Commands for using parlay with ecosystem.ms",
Expand Down
4 changes: 2 additions & 2 deletions internal/commands/scorecard/enrich.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import (
"github.com/snyk/parlay/lib/scorecard"
)

func NewEnrichCommand(logger zerolog.Logger) *cobra.Command {
func NewEnrichCommand(logger *zerolog.Logger) *cobra.Command {
cmd := cobra.Command{
Use: "enrich <sbom>",
Short: "Enrich an SBOM with OpenSSF Scorecard data",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
b, err := utils.GetUserInput(args[0], os.Stdin)
if err != nil {
logger.Fatal().Err(err).Msg("Problem reading input")
logger.Fatal().Err(err).Msg("Failed to read input")
}

doc, err := sbom.DecodeSBOMDocument(b)
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/scorecard/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"github.com/spf13/cobra"
)

func NewRootCommand(logger zerolog.Logger) *cobra.Command {
func NewRootCommand(logger *zerolog.Logger) *cobra.Command {
cmd := cobra.Command{
Use: "scorecard",
Short: "Commands for using parlay with OpenSSF Scorecard",
Expand Down
4 changes: 2 additions & 2 deletions internal/commands/snyk/enrich.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import (
"github.com/snyk/parlay/lib/snyk"
)

func NewEnrichCommand(logger zerolog.Logger) *cobra.Command {
func NewEnrichCommand(logger *zerolog.Logger) *cobra.Command {
cmd := cobra.Command{
Use: "enrich <sbom>",
Short: "Enrich an SBOM with Snyk data",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
b, err := utils.GetUserInput(args[0], os.Stdin)
if err != nil {
logger.Fatal().Err(err).Msg("Problem reading input")
logger.Fatal().Err(err).Msg("Failed to read input")
}

doc, err := sbom.DecodeSBOMDocument(b)
Expand Down
10 changes: 5 additions & 5 deletions internal/commands/snyk/packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import (
"github.com/snyk/parlay/lib/snyk"
)

func NewPackageCommand(logger zerolog.Logger) *cobra.Command {
func NewPackageCommand(logger *zerolog.Logger) *cobra.Command {
cmd := cobra.Command{
Use: "package <purl>",
Short: "Return package vulnerabilities from Snyk",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
purl, err := packageurl.FromString(args[0])
if err != nil {
logger.Fatal().Err(err).Msg("Not a valid purl")
logger.Fatal().Err(err).Msg("Failed to parse PackageURL")
}

logger.
Expand All @@ -31,20 +31,20 @@ func NewPackageCommand(logger zerolog.Logger) *cobra.Command {
logger.
Fatal().
Err(err).
Msg("Failed to get API credentials.")
Msg("Failed to get API credentials")
}

orgID, err := snyk.SnykOrgID(auth)
if err != nil {
logger.
Fatal().
Err(err).
Msg("Failed to look up user info.")
Msg("Failed to look up user info")
}

resp, err := snyk.GetPackageVulnerabilities(&purl, auth, orgID)
if err != nil {
logger.Fatal().Err(err).Msg("An error occurred")
logger.Fatal().Err(err).Msg("Failed to look up package vulnerabilities")
}

fmt.Print(string(resp.Body))
Expand Down
3 changes: 2 additions & 1 deletion internal/commands/snyk/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"github.com/spf13/cobra"
)

func NewSnykRootCommand(logger zerolog.Logger) *cobra.Command {
func NewSnykRootCommand(logger *zerolog.Logger) *cobra.Command {
cmd := cobra.Command{
Use: "snyk",
Short: "Commands for using parlay with Snyk",
Expand All @@ -18,6 +18,7 @@ func NewSnykRootCommand(logger zerolog.Logger) *cobra.Command {
}
},
}

cmd.AddCommand(NewPackageCommand(logger))
cmd.AddCommand(NewEnrichCommand(logger))

Expand Down
7 changes: 4 additions & 3 deletions lib/ecosystems/enrich.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@ package ecosystems

import (
cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/rs/zerolog"
"github.com/spdx/tools-golang/spdx"

"github.com/snyk/parlay/lib/sbom"
)

func EnrichSBOM(doc *sbom.SBOMDocument) *sbom.SBOMDocument {
func EnrichSBOM(doc *sbom.SBOMDocument, logger *zerolog.Logger) *sbom.SBOMDocument {
switch bom := doc.BOM.(type) {
case *cdx.BOM:
enrichCDX(bom)
enrichCDX(bom, logger)
case *spdx.Document:
enrichSPDX(bom)
enrichSPDX(bom, logger)
}
return doc
}
44 changes: 32 additions & 12 deletions lib/ecosystems/enrich_cyclonedx.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/package-url/packageurl-go"
"github.com/remeh/sizedwaitgroup"
"github.com/rs/zerolog"

"github.com/snyk/parlay/ecosystems/packages"
"github.com/snyk/parlay/internal/utils"
Expand Down Expand Up @@ -63,7 +64,7 @@ func enrichCDXLicense(component cdx.Component, packageData packages.Package) cdx
return component
}

func enrichExternalReference(component cdx.Component, packageData packages.Package, url *string, refType cdx.ExternalReferenceType) cdx.Component {
func enrichExternalReference(component cdx.Component, _ packages.Package, url *string, refType cdx.ExternalReferenceType) cdx.Component {
if url == nil {
return component
}
Expand Down Expand Up @@ -192,27 +193,46 @@ func enrichCDXTopics(component cdx.Component, packageData packages.Package) cdx.
return component
}

func enrichCDX(bom *cdx.BOM) {
comps := utils.DiscoverCDXComponents(bom)
func enrichCDX(bom *cdx.BOM, logger *zerolog.Logger) {
wg := sizedwaitgroup.New(20)

comps := utils.DiscoverCDXComponents(bom)
logger.Debug().Msgf("Detected %d packages", len(comps))

for i := range comps {
wg.Add()
go func(component *cdx.Component) {
go func(comp *cdx.Component) {
defer wg.Done()
purl, err := packageurl.FromString(component.PackageURL)
l := logger.With().Str("bom-ref", comp.BOMRef).Logger()

purl, err := packageurl.FromString(comp.PackageURL)
if err != nil {
l.Debug().
Err(err).
Msg("Skipping package: no usable PackageURL")
return
}

resp, err := GetPackageData(purl)
if err == nil {
packageData := resp.JSON200
if packageData != nil {
for _, enrichFunc := range cdxEnrichers {
*component = enrichFunc(*component, *packageData)
}
}
if err != nil {
l.Debug().
Err(err).
Msg("Skipping package: failed to get package data")
return
}

if resp.JSON200 == nil {
l.Debug().
Err(err).
Msg("Skipping package: no data on ecosyste.ms response")
return
}

for _, enrichFunc := range cdxEnrichers {
*comp = enrichFunc(*comp, *resp.JSON200)
}
}(comps[i])
}

wg.Wait()
}
13 changes: 9 additions & 4 deletions lib/ecosystems/enrich_cyclonedx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@ import (

cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/jarcoal/httpmock"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert"

"github.com/snyk/parlay/ecosystems/packages"
"github.com/snyk/parlay/lib/sbom"
)

var logger = zerolog.Nop()

func TestEnrichSBOM_CycloneDX(t *testing.T) {
httpmock.Activate()
defer httpmock.DeactivateAndReset()
Expand Down Expand Up @@ -65,7 +68,7 @@ func TestEnrichSBOM_CycloneDX(t *testing.T) {
}
doc := &sbom.SBOMDocument{BOM: bom}

EnrichSBOM(doc)
EnrichSBOM(doc, &logger)

components := *bom.Components
component := components[0]
Expand Down Expand Up @@ -112,7 +115,7 @@ func TestEnrichSBOM_CycloneDX_NestedComps(t *testing.T) {
}
doc := &sbom.SBOMDocument{BOM: bom}

EnrichSBOM(doc)
EnrichSBOM(doc, &logger)

httpmock.GetTotalCallCount()
calls := httpmock.GetCallCountInfo()
Expand Down Expand Up @@ -144,7 +147,7 @@ func TestEnrichSBOMWithoutLicense(t *testing.T) {
}
doc := &sbom.SBOMDocument{BOM: bom}

EnrichSBOM(doc)
EnrichSBOM(doc, &logger)

components := *bom.Components

Expand Down Expand Up @@ -188,7 +191,9 @@ func TestEnrichLicense(t *testing.T) {
func TestEnrichBlankSBOM(t *testing.T) {
bom := new(cdx.BOM)
doc := &sbom.SBOMDocument{BOM: bom}
EnrichSBOM(doc)

EnrichSBOM(doc, &logger)

assert.Nil(t, bom.Components)
}

Expand Down

0 comments on commit a5f2a63

Please sign in to comment.