Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
81 changes: 77 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* [ecosyste.ms](https://ecosyste.ms)
* [Snyk](https://snyk.io)
* [OpenSSF Scorecard](https://securityscorecards.dev/)
* [deps.dev](https://deps.dev)

By enrich, we mean add additional information. You put in an SBOM, and you get a richer SBOM back. In many cases SBOMs have a minimum of information, often just the name and version of a given package. By enriching that with additional information we can make better decisions about the packages we're using.

Expand Down Expand Up @@ -191,7 +192,7 @@ Snyk will add a new [vulnerability](https://cyclonedx.org/docs/1.4/json/#vulnera
}
```

For SPDX, vulnerability informatio is added as additional `externalRefs`:
For SPDX, vulnerability information is added as additional `externalRefs`:

```json
{
Expand Down Expand Up @@ -246,6 +247,74 @@ This will currently add an external reference to the [Scorecard API](https://api

We're currently looking at the best way of encoding some of the scorecard data in the SBOM itself as well.

## Enriching with deps.dev

The [deps.dev](https://deps.dev) service provides repository insights and security data for open source packages. `parlay` can enrich SBOMs with repository metadata from deps.dev.

```
parlay deps enrich testing/sbom-with-vcs.cyclonedx.json
```

This will add repository information as properties for components that have VCS external references:

```json
{
"bom-ref": "68-subtext@6.0.12",
"type": "library",
"name": "subtext",
"version": "6.0.12",
"purl": "pkg:npm/subtext@6.0.12",
"externalReferences": [
{
"url": "https://github.com/hapijs/subtext",
"type": "vcs"
}
],
"properties": [
{
"name": "deps:open_issues_count",
"value": "7"
},
{
"name": "deps:stars_count",
"value": "24"
},
{
"name": "deps:forks_count",
"value": "25"
},
{
"name": "deps:license",
"value": "non-standard"
},
{
"name": "deps:description",
"value": "HTTP payload parser"
},
{
"name": "deps:scorecard",
"value": "4.30"
}
]
}
```

For SPDX format, the same information is added as external references:

```json
{
"referenceCategory": "OTHER",
"referenceType": "deps:stars_count",
"referenceLocator": "24",
"comment": "deps.dev deps:stars_count"
}
```

You can also return raw JSON information about a specific repository from deps.dev:

```
parlay deps repo github.com/hapijs/subtext
```

## What about enriching with other data sources?

Expand All @@ -256,10 +325,10 @@ There are lots of other sources of package data, and it would be great to add su

`parlay` is a fan of stdin and stdout. You can pipe SBOMs from other tools into `parlay`, and pipe between the separate `enrich` commands too.

Maybe you want to enrich an SBOM with both ecosyste.ms and Snyk data:
Maybe you want to enrich an SBOM with ecosyste.ms, Snyk, and deps.dev data:

```
cat testing/sbom.cyclonedx.json | ./parlay e enrich - | ./parlay s enrich - | jq
cat testing/sbom.cyclonedx.json | ./parlay e enrich - | ./parlay s enrich - | ./parlay d enrich - | jq
```

Maybe you want to take the output from Syft and add vulnerabilitity data?
Expand All @@ -268,7 +337,7 @@ Maybe you want to take the output from Syft and add vulnerabilitity data?
syft -o cyclonedx-json nginx | parlay s enrich - | jq
```

Maybe you want to geneate an SBOM with `cdxgen`, enrich that with extra information, and test that with `bomber`:
Maybe you want to generate an SBOM with `cdxgen`, enrich that with extra information, and test that with `bomber`:

```
cdxgen -o | parlay e enrich - | bomber scan --provider snyk -
Expand Down Expand Up @@ -348,3 +417,7 @@ The various services used to enrich the SBOM data have data for a subset of purl
* `pypi`

Note that Scorecard data is available only for a subset of projects from supported Git repositories. See the [Scorecard project](https://github.com/ossf/scorecard) for more information.

### deps.dev

deps.dev enrichment works with any component that has VCS external references pointing to supported Git repositories (GitHub, GitLab, etc.).
5 changes: 5 additions & 0 deletions acceptance.bats
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,8 @@
run ./parlay ecosystems enrich not-here
[ "$status" -eq 1 ]
}

@test "Not fail when testing deps enrichment" {
run ./parlay deps enrich testing/sbom-with-vcs.cyclonedx.json
[ "$status" -eq 0 ]
}
2 changes: 0 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ go 1.23
require (
github.com/CycloneDX/cyclonedx-go v0.9.2
github.com/deepmap/oapi-codegen v1.12.4
github.com/edoardottt/depsdev v0.0.3
github.com/google/uuid v1.5.0
github.com/hashicorp/go-retryablehttp v0.7.7
github.com/jarcoal/httpmock v1.3.0
Expand All @@ -22,7 +21,6 @@ require (
require (
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/avast/retry-go v3.0.0+incompatible // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
Expand All @@ -65,8 +63,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deepmap/oapi-codegen v1.12.4 h1:pPmn6qI9MuOtCz82WY2Xaw46EQjgvxednXXrP7g5Q2s=
github.com/deepmap/oapi-codegen v1.12.4/go.mod h1:3lgHGMu6myQ2vqbbTXH2H1o4eXFTGnFiDaOaKKl5yas=
github.com/edoardottt/depsdev v0.0.3 h1:QqTZGjdvrq8aZ0qhlPxUHiDrB+LadqUVsHX9a03pWO0=
github.com/edoardottt/depsdev v0.0.3/go.mod h1:IQTpYyqJbheAt6AXD/96CUMSGHha5r6rMLNKD8CXkiY=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
Expand Down
38 changes: 38 additions & 0 deletions internal/commands/deps/enrich.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package deps

import (
"os"

"github.com/snyk/parlay/internal/utils"
"github.com/snyk/parlay/lib/deps"
"github.com/snyk/parlay/lib/sbom"

"github.com/rs/zerolog"
"github.com/spf13/cobra"
)

func NewEnrichCommand(logger *zerolog.Logger) *cobra.Command {
cmd := cobra.Command{
Use: "enrich <sbom>",
Short: "Enrich an SBOM with deps.dev 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("Failed to read input")
}

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

deps.EnrichSBOM(doc, logger)

if err := doc.Encode(os.Stdout); err != nil {
logger.Fatal().Err(err).Msg("Failed to encode new SBOM")
}
},
}
return &cmd
}
1 change: 1 addition & 0 deletions internal/commands/deps/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func NewDepsRootCommand(logger *zerolog.Logger) *cobra.Command {
}

cmd.AddCommand(NewRepoCommand(logger))
cmd.AddCommand(NewEnrichCommand(logger))

return &cmd
}
37 changes: 37 additions & 0 deletions lib/deps/enrich.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* © 2023 Snyk Limited All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package deps

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, logger *zerolog.Logger) *sbom.SBOMDocument {
switch bom := doc.BOM.(type) {
case *cdx.BOM:
enrichCDX(bom, logger)
case *spdx.Document:
enrichSPDX(bom, logger)
default:
logger.Debug().Msg("Unsupported SBOM format for deps.dev enrichment")
}
return doc
}
Loading
Loading