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

add advisory export to OSV format #707

Merged
merged 1 commit into from Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 9 additions & 8 deletions go.mod
@@ -1,6 +1,6 @@
module github.com/wolfi-dev/wolfictl

go 1.21.7
go 1.21.8

require (
chainguard.dev/apko v0.14.1-0.20240308000904-c510767a86aa
Expand Down Expand Up @@ -29,6 +29,7 @@ require (
github.com/go-ini/ini v1.67.0
github.com/google/go-cmp v0.6.0
github.com/google/go-github/v58 v58.0.0
github.com/google/osv-scanner v1.7.1
github.com/google/uuid v1.6.0
github.com/hashicorp/go-version v1.6.0
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f
Expand All @@ -48,14 +49,14 @@ require (
go.opentelemetry.io/otel v1.24.0
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0
go.opentelemetry.io/otel/sdk v1.24.0
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f
golang.org/x/mod v0.16.0
golang.org/x/oauth2 v0.18.0
golang.org/x/sync v0.6.0
golang.org/x/term v0.18.0
golang.org/x/text v0.14.0
golang.org/x/time v0.5.0
golang.org/x/vuln v1.0.1
golang.org/x/vuln v1.0.4
gopkg.in/yaml.v3 v3.0.1
k8s.io/apimachinery v0.29.2
sigs.k8s.io/release-utils v0.7.7
Expand Down Expand Up @@ -86,7 +87,7 @@ require (
github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b // indirect
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a // indirect
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb // indirect
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 // indirect
github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4 // indirect
github.com/anchore/packageurl-go v0.1.1-0.20240202171727-877e1747d426 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
Expand All @@ -105,7 +106,7 @@ require (
github.com/cloudflare/circl v1.3.7 // indirect
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
github.com/containerd/console v1.0.4 // indirect
github.com/containerd/containerd v1.7.11 // indirect
github.com/containerd/continuity v0.4.3 // indirect
github.com/containerd/fifo v1.1.0 // indirect
Expand Down Expand Up @@ -155,7 +156,7 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-containerregistry v0.19.0 // indirect
github.com/google/go-containerregistry v0.19.1 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/licensecheck v0.3.1 // indirect
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
Expand Down Expand Up @@ -213,7 +214,7 @@ require (
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/signal v0.7.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
Expand Down Expand Up @@ -243,7 +244,7 @@ require (
github.com/saferwall/pe v1.5.2 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect
github.com/sahilm/fuzzy v0.1.1 // indirect
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
github.com/sassoftware/go-rpmutils v0.3.0 // indirect
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e // indirect
Expand Down
25 changes: 14 additions & 11 deletions go.sum
Expand Up @@ -242,8 +242,9 @@ github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a h1:nJ2G8zWKASyVC
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a/go.mod h1:ubLFmlsv8/DFUQrZwY5syT5/8Er3ugSr4rDFwHsE3hg=
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb h1:iDMnx6LIjtjZ46C0akqveX83WFzhpTD3eqOthawb5vU=
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb/go.mod h1:DmTY2Mfcv38hsHbG78xMiTDdxFtkHpgYNVDPsF2TgHk=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 h1:6COpXWpHbhWM1wgcQN95TdsmrLTba8KQfPgImBXzkjA=
github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0vW0nnNKJfJieyH/TZ9UYAnTZs5/gHTdAe8=
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ=
github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4 h1:rmZG77uXgE+o2gozGEBoUMpX27lsku+xrMwlmBZJtbg=
Expand Down Expand Up @@ -353,8 +354,8 @@ github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY=
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw=
github.com/containerd/containerd v1.7.11/go.mod h1:5UluHxHTX2rdvYuZ5OJTC5m/KJNs0Zs9wVoJm9zf5ZE=
github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8=
Expand Down Expand Up @@ -576,8 +577,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.19.0 h1:uIsMRBV7m/HDkDxE/nXMnv1q+lOOSPlQ/ywc5JbB8Ic=
github.com/google/go-containerregistry v0.19.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
github.com/google/go-containerregistry v0.19.1 h1:yMQ62Al6/V0Z7CqIrrS1iYoA5/oQCm88DeNujc7C1KY=
github.com/google/go-containerregistry v0.19.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI=
github.com/google/go-github/v58 v58.0.0 h1:Una7GGERlF/37XfkPwpzYJe0Vp4dt2k1kCjlxwjIvzw=
github.com/google/go-github/v58 v58.0.0/go.mod h1:k4hxDKEfoWpSqFlc8LTpGd9fu2KrV1YAa6Hi6FmDNY4=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
Expand All @@ -594,6 +595,8 @@ github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIG
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/osv-scanner v1.7.1 h1:xVLRp7nFNtBphuIF63++T1TW5ViO2eW5UrwyqvKauGk=
github.com/google/osv-scanner v1.7.1/go.mod h1:f1oLmNj+LnHwsJn5UYOY1FASeBL+C13JKI+O7HNahcs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
Expand Down Expand Up @@ -858,8 +861,8 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA=
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
Expand Down Expand Up @@ -977,8 +980,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f h1:MvTmaQdww/z0Q4wrYjDSCcZ78NoftLQyHBSLW/Cx79Y=
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
Expand Down Expand Up @@ -1191,8 +1194,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f h1:3CW0unweImhOzd5FmYuRsD4Y4oQFKZIjAnKbjV4WIrw=
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
Expand Down
117 changes: 116 additions & 1 deletion pkg/advisory/export.go
Expand Up @@ -5,15 +5,21 @@ import (
"encoding/csv"
"fmt"
"io"
"log"
"sort"
"time"

"github.com/google/osv-scanner/pkg/models"
"github.com/samber/lo"
"gopkg.in/yaml.v3"

"github.com/wolfi-dev/wolfictl/pkg/configs"
v2 "github.com/wolfi-dev/wolfictl/pkg/configs/advisory/v2"
"gopkg.in/yaml.v3"
)

type ExportOptions struct {
AdvisoryDocIndices []*configs.Index[v2.Document]
Ecosystem models.Ecosystem
}

// ExportCSV returns a reader of advisory data encoded as CSV.
Expand Down Expand Up @@ -112,3 +118,112 @@ func ExportYAML(opts ExportOptions) (io.Reader, error) {

return buf, nil
}

func ExportOSV(opts ExportOptions) (io.Reader, error) {
buf := new(bytes.Buffer)

osvExport := make(map[string]models.Vulnerability)

for _, index := range opts.AdvisoryDocIndices {
documents := index.Select().Configurations()

for _, doc := range documents {
for _, adv := range doc.Advisories {
sortedEvents := adv.SortedEvents()
var updatedTime time.Time
tempAffected := models.Affected{}
for _, event := range sortedEvents {
switch event.Type {
case v2.EventTypeFixed:
tempAffected.Package = models.Package{
Name: doc.Package.Name,
Ecosystem: opts.Ecosystem,
Purl: fmt.Sprintf("pkg:apk/%s/%s", opts.Ecosystem, doc.Package.Name),
}
tempAffected.Ranges = []models.Range{
{
Type: v2.EventTypeFixed,
Events: []models.Event{
{
Fixed: event.Data.(v2.Fixed).FixedVersion,
},
},
},
}
updatedTime = time.Time(event.Timestamp)
case v2.EventTypeFalsePositiveDetermination:
tempAffected.Package = models.Package{
Name: doc.Package.Name,
Ecosystem: opts.Ecosystem,
Purl: fmt.Sprintf("pkg:apk/%s/%s", opts.Ecosystem, doc.Package.Name),
}
tempAffected.Ranges = []models.Range{
{
Type: v2.EventTypeFixed,
Events: []models.Event{
{
Fixed: "0",
},
},
},
}
updatedTime = time.Time(event.Timestamp)
default:
continue
}

if len(tempAffected.Ranges) == 0 {
continue
}

entry, ok := osvExport[adv.ID]
if ok {
entry.Affected = append(entry.Affected, tempAffected)

if updatedTime.After(entry.Modified) {
entry.Modified = updatedTime
}

osvExport[adv.ID] = entry
} else {
temp := models.Vulnerability{
ID: adv.ID,
Aliases: adv.Aliases,
Affected: []models.Affected{tempAffected},
}
if updatedTime.After(entry.Modified) {
temp.Modified = updatedTime
}

osvExport[adv.ID] = temp
}
}
}
}
}

keys := make([]string, 0, len(osvExport))
for k := range osvExport {
keys = append(keys, k)
}
sort.Strings(keys)

for _, k := range keys {
if len(buf.Bytes()) != 0 {
buf.WriteString("---\n")
}

e, err := osvExport[k].MarshalYAML()
if err != nil {
log.Fatal(err)
}

d, err := yaml.Marshal(e)
if err != nil {
return nil, fmt.Errorf("failed to marshal package %q: %v", osvExport[k].ID, err)
}
buf.Write(d)
}

return buf, nil
}
10 changes: 9 additions & 1 deletion pkg/advisory/export_test.go
Expand Up @@ -4,9 +4,11 @@ import (
"context"
"io"
"os"
"strings"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/osv-scanner/pkg/models"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/wolfi-dev/wolfictl/pkg/configs"
Expand All @@ -32,6 +34,11 @@ func Test_ExportFuncs(t *testing.T) {
exportFuncUnderTest: ExportYAML,
pathToExpectedData: "./testdata/export/expected.yaml",
},
{
name: "osv",
exportFuncUnderTest: ExportOSV,
pathToExpectedData: "./testdata/export/expected-osv.yaml",
},
}

for _, tt := range cases {
Expand All @@ -43,6 +50,7 @@ func Test_ExportFuncs(t *testing.T) {

opts := ExportOptions{
AdvisoryDocIndices: indices,
Ecosystem: models.Ecosystem("wolfi"),
}

exported, err := tt.exportFuncUnderTest(opts)
Expand All @@ -56,7 +64,7 @@ func Test_ExportFuncs(t *testing.T) {
require.NoError(t, err)

if diff := cmp.Diff(string(expectedBytes), string(exportedBytes)); diff != "" {
t.Errorf("ExportCSV() produced unexpected data (-want +got):\n%s", diff)
t.Errorf("Export%s() produced unexpected data (-want +got):\n%s", strings.ToUpper(tt.name), diff)
}
}
})
Expand Down