internal/vulndbclient: add logic for fetching all vulnerabilities
Change-Id: I45df7e8d9abe8f2f9b4e57c198f1a4129e8a8837
Reviewed-on: https://go-review.googlesource.com/c/pkgsite-metrics/+/488175
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Maceo Thompson <maceothompson@google.com>
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
diff --git a/internal/worker/vulndb.go b/internal/worker/vulndb.go
new file mode 100644
index 0000000..f681c6d
--- /dev/null
+++ b/internal/worker/vulndb.go
@@ -0,0 +1,64 @@
+// 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 worker
+
+import (
+ "context"
+ "encoding/json"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "cloud.google.com/go/storage"
+ "golang.org/x/vuln/osv"
+ "google.golang.org/api/iterator"
+)
+
+// gcsOSVPrefix is the directory under which .json
+// files with OSV entries are located.
+const gcsOSVPrefix = "ID"
+
+// allVulnerabilities fetches all osv.Entries from GCS bucket located at ID/*.json paths.
+func allVulnerabilities(ctx context.Context, bucket *storage.BucketHandle) ([]*osv.Entry, error) {
+ var entries []*osv.Entry
+ query := &storage.Query{Prefix: gcsOSVPrefix}
+ it := bucket.Objects(ctx, query)
+ for {
+ attrs, err := it.Next()
+ if err == iterator.Done {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+ // Skip zip files and index.json.
+ if !strings.HasSuffix(attrs.Name, ".json") || strings.HasSuffix(attrs.Name, "index.json") {
+ continue
+ }
+
+ e, err := readEntry(ctx, bucket, attrs.Name)
+ if err != nil {
+ return nil, err
+ }
+ entries = append(entries, e)
+ }
+ return entries, nil
+}
+
+func readEntry(ctx context.Context, bucket *storage.BucketHandle, gcsPath string) (*osv.Entry, error) {
+ localPath := filepath.Join(os.TempDir(), "binary")
+ if err := copyToLocalFile(localPath, false, gcsPath, gcsOpenFileFunc(ctx, bucket)); err != nil {
+ return nil, err
+ }
+ js, err := os.ReadFile(localPath)
+ if err != nil {
+ return nil, err
+ }
+ var entry osv.Entry
+ if err := json.Unmarshal(js, &entry); err != nil {
+ return nil, err
+ }
+ return &entry, nil
+}
diff --git a/internal/worker/vulndb_test.go b/internal/worker/vulndb_test.go
new file mode 100644
index 0000000..c6c2b3f
--- /dev/null
+++ b/internal/worker/vulndb_test.go
@@ -0,0 +1,34 @@
+// Copyright 2022 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 worker
+
+import (
+ "context"
+ "testing"
+
+ "cloud.google.com/go/storage"
+ test "golang.org/x/pkgsite-metrics/internal/testing"
+)
+
+func TestIntegrationAllVulns(t *testing.T) {
+ test.NeedsIntegrationEnv(t)
+
+ ctx := context.Background()
+ c, err := storage.NewClient(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ bucket := c.Bucket("go-vulndb")
+ if bucket == nil {
+ t.Fatal("failed to create go-vulndb bucket")
+ }
+ es, err := allVulnerabilities(ctx, bucket)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(es) == 0 {
+ t.Fatal("want some vulnerabilities; got none")
+ }
+}