Libvuln Usage

Libvuln is the Go package responsible for keeping the database of vulnerabilities consistent, matching container image contents with vulnerabilities, and reporting diffs between updates of the same security database.

Usage

Libvuln is runtime constructed via the libvuln.New method. New requires a libvuln.Opts struct.

Options

package libvuln // import "github.com/quay/claircore/libvuln"

type Options struct {
	// Store is the interface used to persist and retrieve vulnerabilites
	// for of matching.
	Store datastore.MatcherStore
	// Locker provides system-wide locks for the updater subsystem. If the
	// matching work is distributed the lock should be backed by a distributed
	// store.
	Locker LockSource
	// An interval on which Libvuln will check for new security database
	// updates.
	//
	// This duration will have jitter added to it, to help with smearing load on
	// installations.
	UpdateInterval time.Duration
	// A slice of strings representing which updaters libvuln will create.
	//
	// If nil all default UpdaterSets will be used.
	//
	// The following sets are supported:
	// "alpine"
	// "aws"
	// "debian"
	// "oracle"
	// "photon"
	// "pyupio"
	// "rhel"
	// "suse"
	// "ubuntu"
	UpdaterSets []string
	// A list of out-of-tree updaters to run.
	//
	// This list will be merged with any defined UpdaterSets.
	//
	// If you desire no updaters to run do not add an updater
	// into this slice.
	Updaters []driver.Updater
	// A slice of strings representing which
	// matchers will be used.
	//
	// If nil all default Matchers will be used
	//
	// The following names are supported by default:
	// "alpine"
	// "aws"
	// "debian"
	// "oracle"
	// "photon"
	// "python"
	// "rhel"
	// "suse"
	// "ubuntu"
	MatcherNames []string

	// Config holds configuration blocks for MatcherFactories and Matchers,
	// keyed by name.
	MatcherConfigs map[string]driver.MatcherConfigUnmarshaler

	// A list of out-of-tree matchers you'd like libvuln to
	// use.
	//
	// This list will me merged with the default matchers.
	Matchers []driver.Matcher

	// Enrichers is a slice of enrichers to use with all VulnerabilityReport
	// requests.
	Enrichers []driver.Enricher

	// UpdateWorkers controls the number of update workers running concurrently.
	// If less than or equal to zero, a sensible default will be used.
	UpdateWorkers int

	// UpdateRetention controls the number of updates to retain between
	// garbage collection periods.
	//
	// The lowest possible value is 2 in order to compare updates for notification
	// purposes.
	UpdateRetention int

	// If set to true, there will not be a goroutine launched to periodically
	// run updaters.
	DisableBackgroundUpdates bool

	// UpdaterConfigs is a map of functions for configuration of Updaters.
	UpdaterConfigs map[string]driver.ConfigUnmarshaler

	// Client is an http.Client for use by all updaters.
	//
	// Must be set.
	Client *http.Client
}

The above outlines the relevant bits of the Opts structure.

Construction

Constructing Libvuln is straight forward.

	opts := new(libvuln.Options)
	// Populate with desired settings...
	lib, err := libvuln.New(ctx, opts)
	if err != nil {
		panic(err)
	}
	defer lib.Close(ctx)

The constructing code should provide a valid Context tied to some lifetime.

On construction, New will block until the security databases are initialized. Expect some delay before this method returns.

Scanning

Scanning is the process of taking a claircore.IndexReport comprised of a Manifest's content and determining which vulnerabilities affect the Manifest. A claircore.VulnerabilityReport will be returned with these details.

	m := new(claircore.Manifest)
	// Populate somehow ...
	ir, err := indexer.Index(ctx, m)
	if err != nil {
		panic(err)
	}
	vr, err := lib.Scan(ctx, ir)
	if err != nil {
		panic(err)
	}

In the above example, Libindex is used to generate a claircore.IndexReport. The index report is then provided to Libvuln and a subsequent vulnerability report identifying any vulnerabilities affecting the manifest is returned.

Updates API

By default, Libvuln manages a set of long running updaters responsible for periodically fetching and loading new advisory contents into its database. The Updates API allows a client to view and manipulate aspects of the update operations that updaters perform.

In this getting started guide, we will only cover the two methods most interesting to new users.

UpdateOperations

This API provides a list of recent update operations performed by implemented updaters. The UpdateOperation slice returned will be sorted by latest timestamp descending.

	ops, err := lib.UpdateOperations(ctx, `updater`)
	if err != nil {
		panic(err)
	}
	for updater, ops := range ops {
		fmt.Printf("ops for updater %s, %+v", updater, ops)
	}

UpdateDiff

Mostly used by the Clair v4 notification subsystem, this endpoint will provide the caller with any removed or added vulnerabilities between two update operations. Typically a diff takes places against two versions of the same data source. This is useful to inform downstream applications what new vulnerabilities have entered the system.

	ops, err := lib.UpdateOperations(ctx, `updater`)
	if err != nil {
		panic(err)
	}
	for upd, ops := range ops {
		fmt.Printf("updater: %v", upd)
		diff, err := lib.UpdateDiff(ctx, ops[1].Ref, ops[0].Ref)
		if err != nil {
			panic(err)
		}
		for _, vuln := range diff.Added {
			fmt.Printf("vuln %+v added in %v", vuln, diff.Cur.Ref)
		}
	}