Implements #221
This adds a configuration section to config.yaml which allows users to enable/disable each fetcher at runtime. Signed-off-by: Avi Miller <avi.miller@oracle.com>
This commit is contained in:
parent
59ee75c502
commit
ee37c47a4b
@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/coreos/clair"
|
"github.com/coreos/clair"
|
||||||
"github.com/coreos/clair/api"
|
"github.com/coreos/clair/api"
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
|
"github.com/coreos/clair/ext/vulnsrc"
|
||||||
"github.com/coreos/clair/ext/notification"
|
"github.com/coreos/clair/ext/notification"
|
||||||
"github.com/fernet/fernet-go"
|
"github.com/fernet/fernet-go"
|
||||||
)
|
)
|
||||||
@ -43,6 +44,7 @@ type File struct {
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
Database database.RegistrableComponentConfig
|
Database database.RegistrableComponentConfig
|
||||||
Updater *clair.UpdaterConfig
|
Updater *clair.UpdaterConfig
|
||||||
|
Fetcher *vulnsrc.Config
|
||||||
Notifier *notification.Config
|
Notifier *notification.Config
|
||||||
API *api.Config
|
API *api.Config
|
||||||
}
|
}
|
||||||
@ -61,6 +63,7 @@ func DefaultConfig() Config {
|
|||||||
HealthPort: 6061,
|
HealthPort: 6061,
|
||||||
Timeout: 900 * time.Second,
|
Timeout: 900 * time.Second,
|
||||||
},
|
},
|
||||||
|
Fetcher: &vulnsrc.Config {},
|
||||||
Notifier: ¬ification.Config{
|
Notifier: ¬ification.Config{
|
||||||
Attempts: 5,
|
Attempts: 5,
|
||||||
RenotifyInterval: 2 * time.Hour,
|
RenotifyInterval: 2 * time.Hour,
|
||||||
|
@ -110,7 +110,7 @@ func Boot(config *Config) {
|
|||||||
|
|
||||||
// Start updater
|
// Start updater
|
||||||
st.Begin()
|
st.Begin()
|
||||||
go clair.RunUpdater(config.Updater, db, st)
|
go clair.RunUpdater(config.Updater, config.Fetcher, db, st)
|
||||||
|
|
||||||
// Wait for interruption and shutdown gracefully.
|
// Wait for interruption and shutdown gracefully.
|
||||||
waitForSignals(syscall.SIGINT, syscall.SIGTERM)
|
waitForSignals(syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
@ -56,6 +56,22 @@ clair:
|
|||||||
# The value 0 disables the updater entirely.
|
# The value 0 disables the updater entirely.
|
||||||
interval: 2h
|
interval: 2h
|
||||||
|
|
||||||
|
fetcher:
|
||||||
|
# You can enable or disable individual fetchers in this section. This is useful for reducing
|
||||||
|
# overall update times by disabling the distributions you will never scan
|
||||||
|
# The default if a distribution is unspecified/unconfigured is true/enabled.
|
||||||
|
alpine:
|
||||||
|
enabled: true
|
||||||
|
debian:
|
||||||
|
enabled: true
|
||||||
|
oracle:
|
||||||
|
enabled: true
|
||||||
|
rhel:
|
||||||
|
enabled: true
|
||||||
|
ubuntu:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
|
||||||
notifier:
|
notifier:
|
||||||
# Number of attempts before the notification is marked as failed to be sent
|
# Number of attempts before the notification is marked as failed to be sent
|
||||||
attempts: 3
|
attempts: 3
|
||||||
|
@ -19,6 +19,7 @@ package alpine
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -48,10 +49,39 @@ func init() {
|
|||||||
vulnsrc.RegisterUpdater("alpine", &updater{})
|
vulnsrc.RegisterUpdater("alpine", &updater{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
type updater struct {
|
type updater struct {
|
||||||
repositoryLocalPath string
|
repositoryLocalPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *updater) Configure(config *vulnsrc.Config) (bool, error) {
|
||||||
|
var fetcherConfig Config
|
||||||
|
|
||||||
|
// If no configuration for this fetcher, assume enabled
|
||||||
|
if _, ok := config.Params["alpine"]; !ok {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
yamlConfig, err := yaml.Marshal(config.Params["alpine"])
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.New("Invalid configuration for Alpine Linux fetcher.")
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(yamlConfig, &fetcherConfig)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.New("Invalid configuration for Alpine Linux fetcher.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if fetcherConfig.Enabled == true {
|
||||||
|
return true, nil
|
||||||
|
} else {
|
||||||
|
log.Infof("Alpine Linux fetcher disabled.")
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (u *updater) Update(db database.Datastore) (resp vulnsrc.UpdateResponse, err error) {
|
func (u *updater) Update(db database.Datastore) (resp vulnsrc.UpdateResponse, err error) {
|
||||||
log.Info("fetching Alpine vulnerabilities")
|
log.Info("fetching Alpine vulnerabilities")
|
||||||
|
|
||||||
|
@ -20,11 +20,14 @@ import (
|
|||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
@ -55,12 +58,41 @@ type jsonRel struct {
|
|||||||
Urgency string `json:"urgency"`
|
Urgency string `json:"urgency"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
type updater struct{}
|
type updater struct{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
vulnsrc.RegisterUpdater("debian", &updater{})
|
vulnsrc.RegisterUpdater("debian", &updater{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *updater) Configure(config *vulnsrc.Config) (bool, error) {
|
||||||
|
var fetcherConfig Config
|
||||||
|
|
||||||
|
// If no configuration for this fetcher, assume enabled
|
||||||
|
if _, ok := config.Params["debian"]; !ok {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
yamlConfig, err := yaml.Marshal(config.Params["debian"])
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.New("Invalid configuration for Debian fetcher.")
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(yamlConfig, &fetcherConfig)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.New("Invalid configuration for Debian fetcher.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if fetcherConfig.Enabled == true {
|
||||||
|
return true, nil
|
||||||
|
} else {
|
||||||
|
log.Infof("Debian fetcher disabled.")
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (u *updater) Update(datastore database.Datastore) (resp vulnsrc.UpdateResponse, err error) {
|
func (u *updater) Update(datastore database.Datastore) (resp vulnsrc.UpdateResponse, err error) {
|
||||||
log.Info("fetching Debian vulnerabilities")
|
log.Info("fetching Debian vulnerabilities")
|
||||||
|
|
||||||
|
@ -42,9 +42,16 @@ type UpdateResponse struct {
|
|||||||
Vulnerabilities []database.Vulnerability
|
Vulnerabilities []database.Vulnerability
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Params map[string]interface{} `yaml:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
// Updater represents anything that can fetch vulnerabilities and insert them
|
// Updater represents anything that can fetch vulnerabilities and insert them
|
||||||
// into a Clair datastore.
|
// into a Clair datastore.
|
||||||
type Updater interface {
|
type Updater interface {
|
||||||
|
// Check configuration for Updater
|
||||||
|
Configure(*Config) (bool, error)
|
||||||
|
|
||||||
// Update gets vulnerability updates.
|
// Update gets vulnerability updates.
|
||||||
Update(database.Datastore) (UpdateResponse, error)
|
Update(database.Datastore) (UpdateResponse, error)
|
||||||
|
|
||||||
@ -76,6 +83,13 @@ func RegisterUpdater(name string, u Updater) {
|
|||||||
updaters[name] = u
|
updaters[name] = u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UnregisterUpdater(name string) {
|
||||||
|
updatersM.Lock()
|
||||||
|
defer updatersM.Unlock()
|
||||||
|
|
||||||
|
delete(updaters, name)
|
||||||
|
}
|
||||||
|
|
||||||
// Updaters returns the list of the registered Updaters.
|
// Updaters returns the list of the registered Updaters.
|
||||||
func Updaters() map[string]Updater {
|
func Updaters() map[string]Updater {
|
||||||
updatersM.RLock()
|
updatersM.RLock()
|
||||||
|
@ -19,12 +19,15 @@ package oracle
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
@ -79,12 +82,40 @@ type criterion struct {
|
|||||||
Comment string `xml:"comment,attr"`
|
Comment string `xml:"comment,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
type updater struct{}
|
type updater struct{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
vulnsrc.RegisterUpdater("oracle", &updater{})
|
vulnsrc.RegisterUpdater("oracle", &updater{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *updater) Configure(config *vulnsrc.Config) (bool, error) {
|
||||||
|
var fetcherConfig Config
|
||||||
|
|
||||||
|
// If no configuration for this fetcher, assume enabled
|
||||||
|
if _, ok := config.Params["oracle"]; !ok {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
yamlConfig, err := yaml.Marshal(config.Params["oracle"])
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.New("Invalid configuration for Oracle Linux fetcher.")
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(yamlConfig, &fetcherConfig)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.New("Invalid configuration for Oracle Linux fetcher.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if fetcherConfig.Enabled == true {
|
||||||
|
return true, nil
|
||||||
|
} else {
|
||||||
|
log.Infof("Oracle Linux fetcher disabled.")
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (u *updater) Update(datastore database.Datastore) (resp vulnsrc.UpdateResponse, err error) {
|
func (u *updater) Update(datastore database.Datastore) (resp vulnsrc.UpdateResponse, err error) {
|
||||||
log.Info("fetching Oracle Linux vulnerabilities")
|
log.Info("fetching Oracle Linux vulnerabilities")
|
||||||
|
|
||||||
|
@ -19,12 +19,15 @@ package rhel
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
@ -83,12 +86,41 @@ type criterion struct {
|
|||||||
Comment string `xml:"comment,attr"`
|
Comment string `xml:"comment,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
type updater struct{}
|
type updater struct{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
vulnsrc.RegisterUpdater("rhel", &updater{})
|
vulnsrc.RegisterUpdater("rhel", &updater{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *updater) Configure(config *vulnsrc.Config) (bool, error) {
|
||||||
|
var fetcherConfig Config
|
||||||
|
|
||||||
|
// If no configuration for this fetcher, assume enabled
|
||||||
|
if _, ok := config.Params["rhel"]; !ok {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
yamlConfig, err := yaml.Marshal(config.Params["rhel"])
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.New("Invalid configuration for RHEL fetcher.")
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(yamlConfig, &fetcherConfig)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.New("Invalid configuration for RHEL fetcher.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if fetcherConfig.Enabled == true {
|
||||||
|
return true, nil
|
||||||
|
} else {
|
||||||
|
log.Infof("RHEL fetcher disabled.")
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (u *updater) Update(datastore database.Datastore) (resp vulnsrc.UpdateResponse, err error) {
|
func (u *updater) Update(datastore database.Datastore) (resp vulnsrc.UpdateResponse, err error) {
|
||||||
log.Info("fetching RHEL vulnerabilities")
|
log.Info("fetching RHEL vulnerabilities")
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ package ubuntu
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -28,6 +29,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
@ -82,10 +85,39 @@ type updater struct {
|
|||||||
repositoryLocalPath string
|
repositoryLocalPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
vulnsrc.RegisterUpdater("ubuntu", &updater{})
|
vulnsrc.RegisterUpdater("ubuntu", &updater{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *updater) Configure(config *vulnsrc.Config) (bool, error) {
|
||||||
|
var fetcherConfig Config
|
||||||
|
|
||||||
|
// If no configuration for this fetcher, assume enabled
|
||||||
|
if _, ok := config.Params["ubuntu"]; !ok {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
yamlConfig, err := yaml.Marshal(config.Params["ubuntu"])
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.New("Invalid configuration for Ubuntu fetcher.")
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(yamlConfig, &fetcherConfig)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.New("Invalid configuration for Ubuntu fetcher.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if fetcherConfig.Enabled == true {
|
||||||
|
return true, nil
|
||||||
|
} else {
|
||||||
|
log.Infof("Ubuntu fetcher disabled.")
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (u *updater) Update(datastore database.Datastore) (resp vulnsrc.UpdateResponse, err error) {
|
func (u *updater) Update(datastore database.Datastore) (resp vulnsrc.UpdateResponse, err error) {
|
||||||
log.Info("fetching Ubuntu vulnerabilities")
|
log.Info("fetching Ubuntu vulnerabilities")
|
||||||
|
|
||||||
|
16
updater.go
16
updater.go
@ -69,7 +69,7 @@ type UpdaterConfig struct {
|
|||||||
|
|
||||||
// RunUpdater begins a process that updates the vulnerability database at
|
// RunUpdater begins a process that updates the vulnerability database at
|
||||||
// regular intervals.
|
// regular intervals.
|
||||||
func RunUpdater(config *UpdaterConfig, datastore database.Datastore, st *stopper.Stopper) {
|
func RunUpdater(config *UpdaterConfig, fetcherConfig *vulnsrc.Config, datastore database.Datastore, st *stopper.Stopper) {
|
||||||
defer st.End()
|
defer st.End()
|
||||||
|
|
||||||
// Do not run the updater if there is no config or if the interval is 0.
|
// Do not run the updater if there is no config or if the interval is 0.
|
||||||
@ -81,6 +81,20 @@ func RunUpdater(config *UpdaterConfig, datastore database.Datastore, st *stopper
|
|||||||
whoAmI := uuid.New()
|
whoAmI := uuid.New()
|
||||||
log.Infof("updater service started. lock identifier: %s", whoAmI)
|
log.Infof("updater service started. lock identifier: %s", whoAmI)
|
||||||
|
|
||||||
|
for updaterName, updater := range vulnsrc.Updaters() {
|
||||||
|
if configured, err := updater.Configure(fetcherConfig); !configured {
|
||||||
|
vulnsrc.UnregisterUpdater(updaterName)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("could not configure updater '%s': %s'", updaterName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(vulnsrc.Updaters()) == 0 {
|
||||||
|
log.Infof("updater service is disabled")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var stop bool
|
var stop bool
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user