feat: Vuln debug logs
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package vulndb
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
trivydb "github.com/aquasecurity/trivy-db/pkg/db"
|
||||
@@ -33,8 +34,10 @@ type Store struct {
|
||||
// it appends "trivy.db" itself.
|
||||
func Open(dir string) (*Store, error) {
|
||||
if err := trivydb.Init(dir); err != nil {
|
||||
log.Printf("vulndb: open %s: %v", dir, err)
|
||||
return nil, err
|
||||
}
|
||||
log.Printf("vulndb: opened database in %s", dir)
|
||||
return &Store{cfg: trivydb.Config{}}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,12 @@ type Result struct {
|
||||
func Match(src AdvisorySource, os models.OSRelease, pkgs []models.InstalledPackage) ([]Result, error) {
|
||||
bucket, err := Bucket(os.Family, os.VersionID)
|
||||
if err != nil {
|
||||
log.Printf("vulndb: no bucket for family=%q version=%q: %v", os.Family, os.VersionID, err)
|
||||
return nil, err
|
||||
}
|
||||
log.Printf("vulndb: matching %d packages against bucket %q", len(pkgs), bucket)
|
||||
|
||||
var advisoryCount, skipped int
|
||||
var out []Result
|
||||
for _, p := range pkgs {
|
||||
// Debian and Ubuntu advisories are keyed on the source package: one
|
||||
@@ -48,6 +51,10 @@ func Match(src AdvisorySource, os models.OSRelease, pkgs []models.InstalledPacka
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("advisories for %s: %w", srcName, err)
|
||||
}
|
||||
advisoryCount += len(advs)
|
||||
if len(advs) > 0 {
|
||||
Debugf("%s (src %s, installed %s): %d advisories", p.Name, srcName, p.Version, len(advs))
|
||||
}
|
||||
|
||||
for _, a := range advs {
|
||||
// No published fix. Vulnerable, and the finding most in need of
|
||||
@@ -67,8 +74,10 @@ func Match(src AdvisorySource, os models.OSRelease, pkgs []models.InstalledPacka
|
||||
// on the host. Log it — a silent skip is a silent false
|
||||
// negative, which is the direction that hurts.
|
||||
log.Printf("vulndb: compare %s %s vs %s: %v", p.Name, p.Version, a.FixedVersion, err)
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
Debugf("%s %s vs fixed %s (%s): vulnerable=%t", p.Name, p.Version, a.FixedVersion, a.CVEID, older)
|
||||
if older {
|
||||
out = append(out, Result{
|
||||
CVEID: a.CVEID, PackageName: p.Name,
|
||||
@@ -77,5 +86,7 @@ func Match(src AdvisorySource, os models.OSRelease, pkgs []models.InstalledPacka
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Printf("vulndb: bucket %q done: %d packages, %d advisories considered, %d results, %d unparseable comparisons",
|
||||
bucket, len(pkgs), advisoryCount, len(out), skipped)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
@@ -7,9 +7,11 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"oras.land/oras-go/v2"
|
||||
@@ -49,6 +51,24 @@ func Disabled() bool {
|
||||
return strings.EqualFold(os.Getenv("VANTAGE_VULNDB_DISABLED"), "true")
|
||||
}
|
||||
|
||||
// DebugEnabled turns on per-package and per-advisory tracing.
|
||||
//
|
||||
// It is a switch rather than always-on because a single scan asks the store one
|
||||
// question per installed package — ~2000 lines per server, per tick — which
|
||||
// would bury every other subsystem's logs on a fleet of any size. The lifecycle
|
||||
// logs (pull, tick, per-server totals) are unconditional; only the inner loop
|
||||
// is gated.
|
||||
func DebugEnabled() bool {
|
||||
return strings.EqualFold(os.Getenv("VANTAGE_VULN_DEBUG"), "true")
|
||||
}
|
||||
|
||||
// Debugf logs only when VANTAGE_VULN_DEBUG=true.
|
||||
func Debugf(format string, args ...any) {
|
||||
if DebugEnabled() {
|
||||
log.Printf("vulndb[debug]: "+format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// dbMetadata is the subset of trivy-db's metadata.json we read.
|
||||
type dbMetadata struct {
|
||||
Version int `json:"Version"`
|
||||
@@ -62,6 +82,8 @@ type dbMetadata struct {
|
||||
// one that Open would happily accept and scan against.
|
||||
func Pull(ctx context.Context, dir string) (int, error) {
|
||||
ref := Ref()
|
||||
started := time.Now()
|
||||
log.Printf("vulndb: pull starting ref=%s dir=%s", ref, dir)
|
||||
|
||||
parsed, err := registry.ParseReference(ref)
|
||||
if err != nil {
|
||||
@@ -92,6 +114,8 @@ func Pull(ctx context.Context, dir string) (int, error) {
|
||||
if len(man.Layers) == 0 {
|
||||
return 0, fmt.Errorf("artifact %s has no layers", ref)
|
||||
}
|
||||
log.Printf("vulndb: manifest resolved layers=%d digest=%s size=%dB",
|
||||
len(man.Layers), man.Layers[0].Digest, man.Layers[0].Size)
|
||||
|
||||
// Streamed rather than buffered: the layer is ~50MB and there is no reason
|
||||
// to hold it in memory on the way to disk.
|
||||
@@ -110,6 +134,7 @@ func Pull(ctx context.Context, dir string) (int, error) {
|
||||
if err := extractTarGz(rc, staging); err != nil {
|
||||
return 0, fmt.Errorf("extract layer: %w", err)
|
||||
}
|
||||
log.Printf("vulndb: layer extracted into %s after %s", staging, time.Since(started).Round(time.Millisecond))
|
||||
|
||||
metaBytes, err := os.ReadFile(filepath.Join(staging, metaFileName))
|
||||
if err != nil {
|
||||
@@ -123,9 +148,11 @@ func Pull(ctx context.Context, dir string) (int, error) {
|
||||
return 0, fmt.Errorf("trivy-db schema %d is not supported (want %d)", meta.Version, SupportedSchema)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filepath.Join(staging, dbFileName)); err != nil {
|
||||
fi, err := os.Stat(filepath.Join(staging, dbFileName))
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("artifact has no %s: %w", dbFileName, err)
|
||||
}
|
||||
log.Printf("vulndb: %s is %dB, schema %d accepted", dbFileName, fi.Size(), meta.Version)
|
||||
|
||||
// Both files present and the schema accepted, so it is safe to replace.
|
||||
for _, name := range []string{dbFileName, metaFileName} {
|
||||
@@ -139,6 +166,7 @@ func Pull(ctx context.Context, dir string) (int, error) {
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("vulndb: pull complete ref=%s schema=%d in %s", ref, meta.Version, time.Since(started).Round(time.Millisecond))
|
||||
return meta.Version, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user