diff options
| author | Tatiana Bradley <tatianabradley@google.com> | 2023-03-07 16:52:27 -0500 |
|---|---|---|
| committer | Tatiana Bradley <tatianabradley@google.com> | 2023-03-08 18:31:20 +0000 |
| commit | 08176819271a487f4b938e99ee3a5fca0ab78845 (patch) | |
| tree | b7d7dabcf7519ebfd4ce2925c6b5560416d8a7e2 /internal | |
| parent | a0d43ae455c83d630478cbb3f105b1bb4879b419 (diff) | |
| download | go-x-pkgsite-08176819271a487f4b938e99ee3a5fca0ab78845.tar.xz | |
internal/frontend, internal/vulns: isolate references to x/vuln repo
No-op refactor to move all code that depends on x/vuln to the
internal/vuln (renamed from internal/vulns) package. This will allow
us to more easily remove the dependency, as a part of the migration to
the v1 database schema.
For golang/go#58928
Change-Id: Ic8ac2377832d8e4a2a6afbb42729a7e10553665c
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/474255
Reviewed-by: Julie Qiu <julieqiu@google.com>
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Run-TryBot: Tatiana Bradley <tatianabradley@google.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/frontend/search.go | 25 | ||||
| -rw-r--r-- | internal/frontend/search_test.go | 10 | ||||
| -rw-r--r-- | internal/frontend/server.go | 6 | ||||
| -rw-r--r-- | internal/frontend/tabs.go | 4 | ||||
| -rw-r--r-- | internal/frontend/unit.go | 10 | ||||
| -rw-r--r-- | internal/frontend/versions.go | 10 | ||||
| -rw-r--r-- | internal/frontend/versions_test.go | 4 | ||||
| -rw-r--r-- | internal/frontend/vulns.go | 19 | ||||
| -rw-r--r-- | internal/frontend/vulns_test.go | 60 | ||||
| -rw-r--r-- | internal/vuln/cache.go | 94 | ||||
| -rw-r--r-- | internal/vuln/client.go | 49 | ||||
| -rw-r--r-- | internal/vuln/test_client.go | 66 | ||||
| -rw-r--r-- | internal/vuln/vulns.go (renamed from internal/vulns/vulns.go) | 2 | ||||
| -rw-r--r-- | internal/vuln/vulns_test.go (renamed from internal/vulns/vulns_test.go) | 2 |
14 files changed, 257 insertions, 104 deletions
diff --git a/internal/frontend/search.go b/internal/frontend/search.go index c823fa51..7711d298 100644 --- a/internal/frontend/search.go +++ b/internal/frontend/search.go @@ -27,9 +27,8 @@ import ( "golang.org/x/pkgsite/internal/postgres" "golang.org/x/pkgsite/internal/stdlib" "golang.org/x/pkgsite/internal/version" - "golang.org/x/pkgsite/internal/vulns" + "golang.org/x/pkgsite/internal/vuln" "golang.org/x/text/message" - vulnc "golang.org/x/vuln/client" ) // serveSearch applies database data to the search template. Handles endpoint @@ -59,7 +58,7 @@ type searchAction struct { page interface{ setBasePage(basePage) } } -func determineSearchAction(r *http.Request, ds internal.DataSource, vulnClient vulnc.Client) (*searchAction, error) { +func determineSearchAction(r *http.Request, ds internal.DataSource, vulnClient *vuln.Client) (*searchAction, error) { if r.Method != http.MethodGet && r.Method != http.MethodHead { return nil, &serverError{status: http.StatusMethodNotAllowed} } @@ -130,9 +129,9 @@ func determineSearchAction(r *http.Request, ds internal.DataSource, vulnClient v if len(filters) > 0 { symbol = filters[0] } - var getVulnEntries vulns.VulnEntriesFunc + var getVulnEntries vuln.VulnEntriesFunc if vulnClient != nil { - getVulnEntries = vulnClient.GetByModule + getVulnEntries = vulnClient.ByModule } page, err := fetchSearchPage(ctx, db, cq, symbol, pageParams, mode == searchModeSymbol, getVulnEntries) if err != nil { @@ -226,7 +225,7 @@ type SearchResult struct { SymbolGOOS string SymbolGOARCH string SymbolLink string - Vulns []vulns.Vuln + Vulns []vuln.Vuln } type subResult struct { @@ -237,7 +236,7 @@ type subResult struct { // fetchSearchPage fetches data matching the search query from the database and // returns a SearchPage. func fetchSearchPage(ctx context.Context, db *postgres.DB, cq, symbol string, - pageParams paginationParams, searchSymbols bool, getVulnEntries vulns.VulnEntriesFunc) (*SearchPage, error) { + pageParams paginationParams, searchSymbols bool, getVulnEntries vuln.VulnEntriesFunc) (*SearchPage, error) { maxResultCount := maxSearchOffset + pageParams.limit // Pageless search: always start from the beginning. @@ -371,7 +370,7 @@ func searchRequestRedirectPath(ctx context.Context, ds internal.DataSource, quer return fmt.Sprintf("/%s", requestedPath) } -func searchVulnModule(ctx context.Context, mode, cq string, client vulnc.Client) (_ *searchAction, err error) { +func searchVulnModule(ctx context.Context, mode, cq string, client *vuln.Client) (_ *searchAction, err error) { if mode != searchModeVuln { return nil, nil } @@ -401,13 +400,13 @@ EntryLoop: }, nil } -func searchVulnAlias(ctx context.Context, mode, cq string, vulnClient vulnc.Client) (_ *searchAction, err error) { +func searchVulnAlias(ctx context.Context, mode, cq string, vulnClient *vuln.Client) (_ *searchAction, err error) { defer derrors.Wrap(&err, "searchVulnAlias(%q, %q)", mode, cq) if mode != searchModeVuln || !isVulnAlias(cq) { return nil, nil } - aliasEntries, err := vulnClient.GetByAlias(ctx, cq) + aliasEntries, err := vulnClient.ByAlias(ctx, cq) if err != nil { return nil, err } @@ -429,7 +428,7 @@ func searchVulnAlias(ctx context.Context, mode, cq string, vulnClient vulnc.Clie } } -// Regexps that match aliases for Go vulns. +// Regexps that match aliases for Go vuln. var ( cveRegexp = regexp.MustCompile("^CVE-[0-9]{4}-[0-9]+$") ghsaRegexp = regexp.MustCompile("^GHSA-.{4}-.{4}-.{4}$") @@ -608,7 +607,7 @@ func elapsedTime(date time.Time) string { // addVulns adds vulnerability information to search results by consulting the // vulnerability database. -func addVulns(ctx context.Context, rs []*SearchResult, getVulnEntries vulns.VulnEntriesFunc) { +func addVulns(ctx context.Context, rs []*SearchResult, getVulnEntries vuln.VulnEntriesFunc) { // Get all vulns concurrently. var wg sync.WaitGroup // TODO(golang/go#48223): throttle concurrency? @@ -617,7 +616,7 @@ func addVulns(ctx context.Context, rs []*SearchResult, getVulnEntries vulns.Vuln wg.Add(1) go func() { defer wg.Done() - r.Vulns = vulns.VulnsForPackage(ctx, r.ModulePath, r.Version, r.PackagePath, getVulnEntries) + r.Vulns = vuln.VulnsForPackage(ctx, r.ModulePath, r.Version, r.PackagePath, getVulnEntries) }() } wg.Wait() diff --git a/internal/frontend/search_test.go b/internal/frontend/search_test.go index 0b5b2e4d..3306fe3c 100644 --- a/internal/frontend/search_test.go +++ b/internal/frontend/search_test.go @@ -22,7 +22,7 @@ import ( "golang.org/x/pkgsite/internal/licenses" "golang.org/x/pkgsite/internal/postgres" "golang.org/x/pkgsite/internal/testing/sample" - "golang.org/x/pkgsite/internal/vulns" + "golang.org/x/pkgsite/internal/vuln" "golang.org/x/text/language" "golang.org/x/text/message" "golang.org/x/vuln/osv" @@ -39,7 +39,7 @@ func TestDetermineSearchAction(t *testing.T) { for _, v := range modules { postgres.MustInsertModule(ctx, t, testDB, v) } - vc := newVulndbTestClient(testEntries) + vc := vuln.NewTestClient(testEntries) for _, test := range []struct { name string method string @@ -385,7 +385,7 @@ func TestFetchSearchPage(t *testing.T) { DisplayVersion: moduleFoo.Version, Licenses: []string{"MIT"}, CommitTime: elapsedTime(moduleFoo.CommitTime), - Vulns: []vulns.Vuln{{ID: "test", Details: "vuln"}}, + Vulns: []vuln.Vuln{{ID: "test", Details: "vuln"}}, }, }, }, @@ -552,7 +552,7 @@ func TestSearchRequestRedirectPath(t *testing.T) { } func TestSearchVulnAlias(t *testing.T) { - vc := newVulndbTestClient(testEntries) + vc := vuln.NewTestClient(testEntries) for _, test := range []struct { name string mode string @@ -624,7 +624,7 @@ func TestSearchVulnAlias(t *testing.T) { } func TestSearchVulnModulePath(t *testing.T) { - vc := newVulndbTestClient(testEntries) + vc := vuln.NewTestClient(testEntries) for _, test := range []struct { name string mode string diff --git a/internal/frontend/server.go b/internal/frontend/server.go index dae9c635..96c8c3e8 100644 --- a/internal/frontend/server.go +++ b/internal/frontend/server.go @@ -37,9 +37,9 @@ import ( "golang.org/x/pkgsite/internal/queue" "golang.org/x/pkgsite/internal/static" "golang.org/x/pkgsite/internal/version" + "golang.org/x/pkgsite/internal/vuln" "golang.org/x/text/cases" "golang.org/x/text/language" - vulnc "golang.org/x/vuln/client" ) // Server can be installed to serve the go discovery frontend. @@ -59,7 +59,7 @@ type Server struct { serveStats bool reportingClient *errorreporting.Client fileMux *http.ServeMux - vulnClient vulnc.Client + vulnClient *vuln.Client versionID string instanceID string @@ -81,7 +81,7 @@ type ServerConfig struct { DevMode bool StaticPath string // used only for dynamic loading in dev mode ReportingClient *errorreporting.Client - VulndbClient vulnc.Client + VulndbClient *vuln.Client } // NewServer creates a new Server for the given database and template directory. diff --git a/internal/frontend/tabs.go b/internal/frontend/tabs.go index 52da9236..cd841eef 100644 --- a/internal/frontend/tabs.go +++ b/internal/frontend/tabs.go @@ -11,7 +11,7 @@ import ( "golang.org/x/pkgsite/internal" "golang.org/x/pkgsite/internal/derrors" - "golang.org/x/pkgsite/internal/vulns" + "golang.org/x/pkgsite/internal/vuln" ) // TabSettings defines tab-specific metadata. @@ -78,7 +78,7 @@ func init() { // handler. func fetchDetailsForUnit(ctx context.Context, r *http.Request, tab string, ds internal.DataSource, um *internal.UnitMeta, requestedVersion string, bc internal.BuildContext, - getVulnEntries vulns.VulnEntriesFunc) (_ any, err error) { + getVulnEntries vuln.VulnEntriesFunc) (_ any, err error) { defer derrors.Wrap(&err, "fetchDetailsForUnit(r, %q, ds, um=%q,%q,%q)", tab, um.Path, um.ModulePath, um.Version) switch tab { case tabMain: diff --git a/internal/frontend/unit.go b/internal/frontend/unit.go index e282d59c..c5194d8f 100644 --- a/internal/frontend/unit.go +++ b/internal/frontend/unit.go @@ -21,7 +21,7 @@ import ( "golang.org/x/pkgsite/internal/middleware" "golang.org/x/pkgsite/internal/stdlib" "golang.org/x/pkgsite/internal/version" - "golang.org/x/pkgsite/internal/vulns" + "golang.org/x/pkgsite/internal/vuln" ) // UnitPage contains data needed to render the unit template. @@ -92,7 +92,7 @@ type UnitPage struct { Details any // Vulns holds vulnerability information. - Vulns []vulns.Vuln + Vulns []vuln.Vuln // DepsDevURL holds the full URL to this module version on deps.dev. DepsDevURL string @@ -135,9 +135,9 @@ func (s *Server) serveUnitPage(ctx context.Context, w http.ResponseWriter, r *ht // It's also okay to provide just one (e.g. GOOS=windows), which will select // the first doc with that value, ignoring the other one. bc := internal.BuildContext{GOOS: r.FormValue("GOOS"), GOARCH: r.FormValue("GOARCH")} - var getVulnEntries vulns.VulnEntriesFunc + var getVulnEntries vuln.VulnEntriesFunc if s.vulnClient != nil { - getVulnEntries = s.vulnClient.GetByModule + getVulnEntries = s.vulnClient.ByModule } d, err := fetchDetailsForUnit(ctx, r, tab, ds, um, info.requestedVersion, bc, getVulnEntries) if err != nil { @@ -241,7 +241,7 @@ func (s *Server) serveUnitPage(ctx context.Context, w http.ResponseWriter, r *ht // Get vulnerability information. if s.vulnClient != nil { - page.Vulns = vulns.VulnsForPackage(ctx, um.ModulePath, um.Version, um.Path, s.vulnClient.GetByModule) + page.Vulns = vuln.VulnsForPackage(ctx, um.ModulePath, um.Version, um.Path, s.vulnClient.ByModule) } s.servePage(ctx, w, tabSettings.TemplateName, page) return nil diff --git a/internal/frontend/versions.go b/internal/frontend/versions.go index 94786958..58d6a515 100644 --- a/internal/frontend/versions.go +++ b/internal/frontend/versions.go @@ -18,7 +18,7 @@ import ( "golang.org/x/pkgsite/internal/postgres" "golang.org/x/pkgsite/internal/stdlib" "golang.org/x/pkgsite/internal/version" - "golang.org/x/pkgsite/internal/vulns" + "golang.org/x/pkgsite/internal/vuln" ) // VersionsDetails contains the hierarchy of version summary information used @@ -82,10 +82,10 @@ type VersionSummary struct { RetractionRationale string IsMinor bool Symbols [][]*Symbol - Vulns []vulns.Vuln + Vulns []vuln.Vuln } -func fetchVersionsDetails(ctx context.Context, ds internal.DataSource, um *internal.UnitMeta, getVulnEntries vulns.VulnEntriesFunc) (*VersionsDetails, error) { +func fetchVersionsDetails(ctx context.Context, ds internal.DataSource, um *internal.UnitMeta, getVulnEntries vuln.VulnEntriesFunc) (*VersionsDetails, error) { db, ok := ds.(*postgres.DB) if !ok { // The proxydatasource does not support the imported by page. @@ -146,7 +146,7 @@ func buildVersionDetails(ctx context.Context, currentModulePath, packagePath str modInfos []*internal.ModuleInfo, sh *internal.SymbolHistory, linkify func(v *internal.ModuleInfo) string, - getVulnEntries vulns.VulnEntriesFunc, + getVulnEntries vuln.VulnEntriesFunc, ) *VersionsDetails { // lists organizes versions by VersionListKey. lists := make(map[VersionListKey]*VersionList) @@ -201,7 +201,7 @@ func buildVersionDetails(ctx context.Context, currentModulePath, packagePath str if mi.ModulePath == stdlib.ModulePath { pkg = packagePath } - vs.Vulns = vulns.VulnsForPackage(ctx, mi.ModulePath, mi.Version, pkg, getVulnEntries) + vs.Vulns = vuln.VulnsForPackage(ctx, mi.ModulePath, mi.Version, pkg, getVulnEntries) vl := lists[key] if vl == nil { seenLists = append(seenLists, key) diff --git a/internal/frontend/versions_test.go b/internal/frontend/versions_test.go index ffe83e43..756c8b5b 100644 --- a/internal/frontend/versions_test.go +++ b/internal/frontend/versions_test.go @@ -14,7 +14,7 @@ import ( "golang.org/x/pkgsite/internal/stdlib" "golang.org/x/pkgsite/internal/testing/sample" "golang.org/x/pkgsite/internal/version" - "golang.org/x/pkgsite/internal/vulns" + "golang.org/x/pkgsite/internal/vuln" "golang.org/x/vuln/osv" ) @@ -150,7 +150,7 @@ func TestFetchPackageVersionsDetails(t *testing.T) { ThisModule: []*VersionList{ func() *VersionList { vl := makeList(v1Path, modulePath1, "v1", []string{"v1.3.0", "v1.2.3", "v1.2.1"}, false) - vl.Versions[2].Vulns = []vulns.Vuln{{ + vl.Versions[2].Vulns = []vuln.Vuln{{ Details: vulnEntry.Details, }} return vl diff --git a/internal/frontend/vulns.go b/internal/frontend/vulns.go index 60a0dc61..ae90202b 100644 --- a/internal/frontend/vulns.go +++ b/internal/frontend/vulns.go @@ -12,9 +12,8 @@ import ( "golang.org/x/pkgsite/internal" "golang.org/x/pkgsite/internal/derrors" - "golang.org/x/pkgsite/internal/vulns" + "golang.org/x/pkgsite/internal/vuln" "golang.org/x/sync/errgroup" - vulnc "golang.org/x/vuln/client" "golang.org/x/vuln/osv" ) @@ -34,7 +33,7 @@ type VulnListPage struct { type VulnPage struct { basePage Entry OSVEntry - AffectedPackages []*vulns.AffectedPackage + AffectedPackages []*vuln.AffectedPackage AliasLinks []link AdvisoryLinks []link } @@ -105,8 +104,8 @@ func (s *Server) serveVuln(w http.ResponseWriter, r *http.Request, _ internal.Da return nil } -func newVulnPage(ctx context.Context, client vulnc.Client, id string) (*VulnPage, error) { - entry, err := client.GetByID(ctx, id) +func newVulnPage(ctx context.Context, client *vuln.Client, id string) (*VulnPage, error) { + entry, err := client.ByID(ctx, id) if err != nil { return nil, derrors.VulnDBError } @@ -115,13 +114,13 @@ func newVulnPage(ctx context.Context, client vulnc.Client, id string) (*VulnPage } return &VulnPage{ Entry: OSVEntry{entry}, - AffectedPackages: vulns.AffectedPackages(entry), + AffectedPackages: vuln.AffectedPackages(entry), AliasLinks: aliasLinks(entry), AdvisoryLinks: advisoryLinks(entry), }, nil } -func newVulnListPage(ctx context.Context, client vulnc.Client) (*VulnListPage, error) { +func newVulnListPage(ctx context.Context, client *vuln.Client) (*VulnListPage, error) { entries, err := vulnList(ctx, client) if err != nil { return nil, err @@ -131,10 +130,10 @@ func newVulnListPage(ctx context.Context, client vulnc.Client) (*VulnListPage, e return &VulnListPage{Entries: entries}, nil } -func vulnList(ctx context.Context, client vulnc.Client) ([]OSVEntry, error) { +func vulnList(ctx context.Context, client *vuln.Client) ([]OSVEntry, error) { const concurrency = 4 - ids, err := client.ListIDs(ctx) + ids, err := client.IDs(ctx) if err != nil { return nil, derrors.VulnDBError } @@ -148,7 +147,7 @@ func vulnList(ctx context.Context, client vulnc.Client) ([]OSVEntry, error) { sem <- struct{}{} g.Go(func() error { defer func() { <-sem }() - e, err := client.GetByID(ctx, id) + e, err := client.ByID(ctx, id) if err != nil { return err } diff --git a/internal/frontend/vulns_test.go b/internal/frontend/vulns_test.go index c98ef421..f211227a 100644 --- a/internal/frontend/vulns_test.go +++ b/internal/frontend/vulns_test.go @@ -6,12 +6,11 @@ package frontend import ( "context" - "errors" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - vulnc "golang.org/x/vuln/client" + "golang.org/x/pkgsite/internal/vuln" "golang.org/x/vuln/osv" ) @@ -40,7 +39,7 @@ var testEntries = []*osv.Entry{ func TestNewVulnListPage(t *testing.T) { ctx := context.Background() - c := newVulndbTestClient(testEntries) + c := vuln.NewTestClient(testEntries) got, err := newVulnListPage(ctx, c) if err != nil { t.Fatal(err) @@ -58,7 +57,7 @@ func TestNewVulnListPage(t *testing.T) { func TestNewVulnPage(t *testing.T) { ctx := context.Background() - c := &vulndbTestClient{entries: testEntries} + c := vuln.NewTestClient(testEntries) got, err := newVulnPage(ctx, c, "GO-1990-02") if err != nil { t.Fatal(err) @@ -72,59 +71,6 @@ func TestNewVulnPage(t *testing.T) { } } -type vulndbTestClient struct { - vulnc.Client - entries []*osv.Entry - aliasToIDs map[string][]string -} - -func newVulndbTestClient(entries []*osv.Entry) *vulndbTestClient { - c := &vulndbTestClient{ - entries: entries, - aliasToIDs: map[string][]string{}, - } - for _, e := range entries { - for _, a := range e.Aliases { - c.aliasToIDs[a] = append(c.aliasToIDs[a], e.ID) - } - } - return c -} - -func (c *vulndbTestClient) GetByModule(context.Context, string) ([]*osv.Entry, error) { - return nil, errors.New("unimplemented") -} - -func (c *vulndbTestClient) GetByID(_ context.Context, id string) (*osv.Entry, error) { - for _, e := range c.entries { - if e.ID == id { - return e, nil - } - } - return nil, nil -} - -func (c *vulndbTestClient) ListIDs(context.Context) ([]string, error) { - var ids []string - for _, e := range c.entries { - ids = append(ids, e.ID) - } - return ids, nil -} - -func (c *vulndbTestClient) GetByAlias(ctx context.Context, alias string) ([]*osv.Entry, error) { - ids := c.aliasToIDs[alias] - if len(ids) == 0 { - return nil, nil - } - var es []*osv.Entry - for _, id := range ids { - e, _ := c.GetByID(ctx, id) - es = append(es, e) - } - return es, nil -} - func Test_aliasLinks(t *testing.T) { type args struct { e *osv.Entry diff --git a/internal/vuln/cache.go b/internal/vuln/cache.go new file mode 100644 index 00000000..22cbe0d2 --- /dev/null +++ b/internal/vuln/cache.go @@ -0,0 +1,94 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package vuln + +import ( + "fmt" + "sync" + "time" + + lru "github.com/hashicorp/golang-lru" + vulnc "golang.org/x/vuln/client" + "golang.org/x/vuln/osv" +) + +// cache implements the golang.org/x/vulndb/client.Cache interface. It +// stores in memory the index and a limited number of path entries for one DB. +type cache struct { + mu sync.Mutex + dbName string // support only one DB + index vulnc.DBIndex + retrieved time.Time + entryCache *lru.Cache +} + +func newCache() *cache { + const size = 100 + ec, err := lru.New(size) + if err != nil { + // Can only happen if size is bad, and we control it. + panic(err) + } + return &cache{entryCache: ec} +} + +// ReadIndex returns the index for dbName from the cache, or returns zero values +// if it is not present. +func (c *cache) ReadIndex(dbName string) (vulnc.DBIndex, time.Time, error) { + c.mu.Lock() + defer c.mu.Unlock() + if err := c.checkDB(dbName); err != nil { + return nil, time.Time{}, err + } + return c.index, c.retrieved, nil +} + +// WriteIndex puts the index and retrieved time into the cache. +func (c *cache) WriteIndex(dbName string, index vulnc.DBIndex, retrieved time.Time) error { + c.mu.Lock() + defer c.mu.Unlock() + if err := c.checkDB(dbName); err != nil { + return err + } + c.index = index + c.retrieved = retrieved + return nil +} + +// ReadEntries returns the vulndb entries for path from the cache, or +// nil if not prsent. +func (c *cache) ReadEntries(dbName, path string) ([]*osv.Entry, error) { + c.mu.Lock() + defer c.mu.Unlock() + if err := c.checkDB(dbName); err != nil { + return nil, err + } + if entries, ok := c.entryCache.Get(path); ok { + return entries.([]*osv.Entry), nil + } + return nil, nil +} + +// WriteEntries puts the entries for path into the cache. +func (c *cache) WriteEntries(dbName, path string, entries []*osv.Entry) error { + c.mu.Lock() + defer c.mu.Unlock() + if err := c.checkDB(dbName); err != nil { + return err + } + c.entryCache.Add(path, entries) + return nil +} + +func (c *cache) checkDB(name string) error { + if c.dbName == "" { + c.dbName = name + return nil + } + if c.dbName != name { + return fmt.Errorf("vulndbCache: called with db name %q, expected %q", name, c.dbName) + } + return nil +} diff --git a/internal/vuln/client.go b/internal/vuln/client.go new file mode 100644 index 00000000..9a6393bb --- /dev/null +++ b/internal/vuln/client.go @@ -0,0 +1,49 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package vuln + +import ( + "context" + + vulnc "golang.org/x/vuln/client" + "golang.org/x/vuln/osv" +) + +// Client reads Go vulnerability databases. +type Client struct { + c vulnc.Client +} + +// NewClient returns a client that can read from the vulnerability +// database in src (a URL or local directory). +func NewClient(src string) (*Client, error) { + c, err := vulnc.NewClient([]string{src}, vulnc.Options{ + HTTPCache: newCache(), + }) + if err != nil { + return nil, err + } + return &Client{c: c}, nil +} + +// ByModule returns the OSV entries that affect the given module path. +func (c *Client) ByModule(ctx context.Context, modulePath string) ([]*osv.Entry, error) { + return c.c.GetByModule(ctx, modulePath) +} + +// ByID returns the OSV entry with the given ID. +func (c *Client) ByID(ctx context.Context, id string) (*osv.Entry, error) { + return c.c.GetByID(ctx, id) +} + +// ByAlias returns the OSV entries that have the given alias. +func (c *Client) ByAlias(ctx context.Context, alias string) ([]*osv.Entry, error) { + return c.c.GetByAlias(ctx, alias) +} + +// IDs returns the IDs of all the entries in the database. +func (c *Client) IDs(ctx context.Context) ([]string, error) { + return c.c.ListIDs(ctx) +} diff --git a/internal/vuln/test_client.go b/internal/vuln/test_client.go new file mode 100644 index 00000000..463a9ae3 --- /dev/null +++ b/internal/vuln/test_client.go @@ -0,0 +1,66 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package vuln + +import ( + "context" + "errors" + + vulnc "golang.org/x/vuln/client" + "golang.org/x/vuln/osv" +) + +func NewTestClient(entries []*osv.Entry) *Client { + c := &vulndbTestClient{ + entries: entries, + aliasToIDs: map[string][]string{}, + } + for _, e := range entries { + for _, a := range e.Aliases { + c.aliasToIDs[a] = append(c.aliasToIDs[a], e.ID) + } + } + return &Client{c: c} +} + +type vulndbTestClient struct { + vulnc.Client + entries []*osv.Entry + aliasToIDs map[string][]string +} + +func (c *vulndbTestClient) GetByModule(context.Context, string) ([]*osv.Entry, error) { + return nil, errors.New("unimplemented") +} + +func (c *vulndbTestClient) GetByID(_ context.Context, id string) (*osv.Entry, error) { + for _, e := range c.entries { + if e.ID == id { + return e, nil + } + } + return nil, nil +} + +func (c *vulndbTestClient) ListIDs(context.Context) ([]string, error) { + var ids []string + for _, e := range c.entries { + ids = append(ids, e.ID) + } + return ids, nil +} + +func (c *vulndbTestClient) GetByAlias(ctx context.Context, alias string) ([]*osv.Entry, error) { + ids := c.aliasToIDs[alias] + if len(ids) == 0 { + return nil, nil + } + var es []*osv.Entry + for _, id := range ids { + e, _ := c.GetByID(ctx, id) + es = append(es, e) + } + return es, nil +} diff --git a/internal/vulns/vulns.go b/internal/vuln/vulns.go index 15ffb543..4263bdb6 100644 --- a/internal/vulns/vulns.go +++ b/internal/vuln/vulns.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Package vulns provides utilities to interact with vuln APIs. -package vulns +package vuln import ( "context" diff --git a/internal/vulns/vulns_test.go b/internal/vuln/vulns_test.go index 831e4937..c723d122 100644 --- a/internal/vulns/vulns_test.go +++ b/internal/vuln/vulns_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package vulns +package vuln import ( "context" |
