internal/worker: make go-vulndb path consistent and explicit
- Sandbox and docker use the same location of go-vulndb
- We pass this location to the sandbox instead of hardcoding it into the
sandbox implementation
- scanner now uses this path, which enables testing
The vulndb location is dictated via GO_ECOSYSTEM_VULNDB_DIR environment
variable, similar to how directory with binaries is handled.
Change-Id: I738c4fd454ae28def478c0440147a78564bb5772
Reviewed-on: https://go-review.googlesource.com/c/pkgsite-metrics/+/477358
Reviewed-by: Jonathan Amsterdam <jba@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
diff --git a/cmd/govulncheck_sandbox/govulncheck_sandbox.go b/cmd/govulncheck_sandbox/govulncheck_sandbox.go
index 94c252d..a8ef94c 100644
--- a/cmd/govulncheck_sandbox/govulncheck_sandbox.go
+++ b/cmd/govulncheck_sandbox/govulncheck_sandbox.go
@@ -25,24 +25,26 @@
"golang.org/x/pkgsite-metrics/internal/worker"
)
-// vulnDBDir should contain a local copy of the vuln DB, with a LAST_MODIFIED
-// file containing a timestamp.
-var vulnDBDir = flag.String("vulndb", "/go-vulndb", "directory of local vuln DB")
-
+// main function for govulncheck sandbox that accepts four inputs
+// in the following order:
+// - path to govulncheck
+// - govulncheck mode
+// - input module or binary to analyze
+// - full path to the vulnerability database
func main() {
flag.Parse()
- run(os.Stdout, flag.Args(), *vulnDBDir)
+ run(os.Stdout, flag.Args())
}
-func run(w io.Writer, args []string, vulnDBDir string) {
+func run(w io.Writer, args []string) {
fail := func(err error) {
fmt.Fprintf(w, `{"Error": %q}`, err)
fmt.Fprintln(w)
}
- if len(args) != 3 {
- fail(errors.New("need three args: govulncheck path, mode, and module dir or binary"))
+ if len(args) != 4 {
+ fail(errors.New("need four args: govulncheck path, mode, input module dir or binary, full path to vuln db"))
return
}
mode := args[1]
@@ -51,7 +53,7 @@
return
}
- resp, err := runGovulncheck(args[0], mode, args[2], vulnDBDir)
+ resp, err := runGovulncheck(args[0], mode, args[2], args[3])
if err != nil {
fail(err)
return
diff --git a/cmd/govulncheck_sandbox/govulncheck_sandbox_test.go b/cmd/govulncheck_sandbox/govulncheck_sandbox_test.go
index 486b79c..59fb837 100644
--- a/cmd/govulncheck_sandbox/govulncheck_sandbox_test.go
+++ b/cmd/govulncheck_sandbox/govulncheck_sandbox_test.go
@@ -59,7 +59,7 @@
}
t.Run("source", func(t *testing.T) {
- resp, err := runTest([]string{govulncheckPath, worker.ModeGovulncheck, "testdata/module"}, vulndb)
+ resp, err := runTest([]string{govulncheckPath, worker.ModeGovulncheck, "testdata/module", vulndb})
if err != nil {
t.Fatal(err)
}
@@ -82,7 +82,7 @@
t.Fatal(derrors.IncludeStderr(err))
}
defer os.Remove(binary)
- resp, err := runTest([]string{govulncheckPath, worker.ModeBinary, binary}, vulndb)
+ resp, err := runTest([]string{govulncheckPath, worker.ModeBinary, binary, vulndb})
if err != nil {
t.Fatal(err)
}
@@ -91,38 +91,33 @@
// Errors
for _, test := range []struct {
- name string
- args []string
- vulndb string
- want string
+ name string
+ args []string
+ want string
}{
{
- name: "too few args",
- args: []string{"testdata/module"},
- vulndb: vulndb,
- want: "need three args",
+ name: "too few args",
+ args: []string{"testdata/module", vulndb},
+ want: "need four args",
},
{
- name: "no vulndb",
- args: []string{govulncheckPath, worker.ModeGovulncheck, "testdata/module"},
- vulndb: "does not exist",
- want: "does not exist",
+ name: "no vulndb",
+ args: []string{govulncheckPath, worker.ModeGovulncheck, "testdata/module", "does not exist"},
+ want: "does not exist",
},
{
- name: "no mode",
- args: []string{govulncheckPath, "MODE", "testdata/module"},
- vulndb: vulndb,
- want: "not a valid mode",
+ name: "no mode",
+ args: []string{govulncheckPath, "MODE", "testdata/module", vulndb},
+ want: "not a valid mode",
},
{
- name: "no module",
- args: []string{govulncheckPath, worker.ModeGovulncheck, "testdata/nosuchmodule"},
- vulndb: vulndb,
- want: "no such file",
+ name: "no module",
+ args: []string{govulncheckPath, worker.ModeGovulncheck, "testdata/nosuchmodule", vulndb},
+ want: "no such file",
},
} {
t.Run(test.name, func(t *testing.T) {
- _, err := runTest(test.args, test.vulndb)
+ _, err := runTest(test.args)
if err == nil {
t.Fatal("got nil, want error")
}
@@ -133,8 +128,8 @@
}
}
-func runTest(args []string, vulndbDir string) (*govulncheck.SandboxResponse, error) {
+func runTest(args []string) (*govulncheck.SandboxResponse, error) {
var buf bytes.Buffer
- run(&buf, args, vulndbDir)
+ run(&buf, args)
return govulncheck.UnmarshalSandboxResponse(buf.Bytes())
}
diff --git a/cmd/worker/Dockerfile b/cmd/worker/Dockerfile
index 775d554..7ecf4cf 100644
--- a/cmd/worker/Dockerfile
+++ b/cmd/worker/Dockerfile
@@ -57,8 +57,10 @@
COPY go-image.tar.gz .
RUN tar --same-owner -pxzf go-image.tar.gz -C rootfs
-# Copy the downloaded copy of the vuln DB into the bundle root.
-COPY go-vulndb rootfs/go-vulndb
+# Copy the downloaded copy of the vuln DB
+# into the /app dir similar to binaries.
+ARG VULNDB_DIR=/app/go-vulndb
+COPY go-vulndb $VULNDB_DIR
COPY config.json .
@@ -105,4 +107,6 @@
ENV GO_ECOSYSTEM_BINARY_DIR=$BINARY_DIR
+ENV GO_ECOSYSTEM_VULNDB_DIR=$VULNDB_DIR
+
CMD ["./worker"]
diff --git a/config.json.commented b/config.json.commented
index 1d87669..30a0932 100644
--- a/config.json.commented
+++ b/config.json.commented
@@ -107,6 +107,14 @@
"options": ["bind"]
},
{
+ # Mount /app/go-vulndb inside the sandbox to
+ # the same directory outside.
+ "destination": "/app/go-vulndb",
+ "type": "none",
+ "source": "/app/go-vulndb",
+ "options": ["bind"]
+ },
+ {
# Mount /tmp/modules inside the sandbox to
# the same directory outside.
"destination": "/tmp/modules",
diff --git a/internal/config/config.go b/internal/config/config.go
index 0e5bbde..6a9212e 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -86,6 +86,9 @@
// BinaryDir is the local directory for binaries.
BinaryDir string
+ // VulnDBDir is the local directory of the vulnerability database.
+ VulnDBDir string
+
// The host, port and user of the pkgsite database used to find
// modules to scan.
PkgsiteDBHost string
@@ -128,6 +131,7 @@
VulnDBBucketProjectID: os.Getenv("GO_ECOSYSTEM_VULNDB_BUCKET_PROJECT"),
BinaryBucket: os.Getenv("GO_ECOSYSTEM_BINARY_BUCKET"),
BinaryDir: GetEnv("GO_ECOSYSTEM_BINARY_DIR", "/tmp/binaries"),
+ VulnDBDir: GetEnv("GO_ECOSYSTEM_VULNDB_DIR", "/tmp/go-vulndb"),
PkgsiteDBHost: GetEnv("GO_ECOSYSTEM_PKGSITE_DB_HOST", "localhost"),
PkgsiteDBPort: GetEnv("GO_ECOSYSTEM_PKGSITE_DB_PORT", "5432"),
PkgsiteDBName: GetEnv("GO_ECOSYSTEM_PKGSITE_DB_NAME", "discovery-db"),
diff --git a/internal/worker/govulncheck_scan.go b/internal/worker/govulncheck_scan.go
index dadc28c..5086f36 100644
--- a/internal/worker/govulncheck_scan.go
+++ b/internal/worker/govulncheck_scan.go
@@ -135,6 +135,7 @@
binaryDir string
govulncheckPath string
+ vulnDBDir string
}
func newScanner(ctx context.Context, h *GovulncheckServer) (*scanner, error) {
@@ -162,6 +163,7 @@
sbox: sbox,
binaryDir: h.cfg.BinaryDir,
govulncheckPath: filepath.Join(h.cfg.BinaryDir, "govulncheck"),
+ vulnDBDir: h.cfg.VulnDBDir,
}, nil
}
@@ -382,7 +384,7 @@
func (s *scanner) runGovulncheckSandbox(ctx context.Context, mode, arg string) (*govulncheck.SandboxResponse, error) {
log.Infof(ctx, "running govulncheck in sandbox: mode %s, arg %q", mode, arg)
- cmd := s.sbox.Command(filepath.Join(s.binaryDir, "govulncheck_sandbox"), s.govulncheckPath, mode, arg)
+ cmd := s.sbox.Command(filepath.Join(s.binaryDir, "govulncheck_sandbox"), s.govulncheckPath, mode, arg, s.vulnDBDir)
stdout, err := cmd.Output()
log.Infof(ctx, "govulncheck in sandbox finished with err=%v", err)
if err != nil {
@@ -427,6 +429,7 @@
func (s *scanner) runGovulncheckCmd(pattern, tempDir string, stats *scanStats) ([]*govulncheckapi.Vuln, error) {
start := time.Now()
govulncheckCmd := exec.Command(s.govulncheckPath, "-json", pattern)
+ govulncheckCmd.Env = append(govulncheckCmd.Environ(), "GOVULNDB=file://"+s.vulnDBDir)
govulncheckCmd.Dir = tempDir
output, err := govulncheckCmd.Output()
if err != nil {