diff --git a/cmd/clair/config.go b/cmd/clair/config.go index 08f26066..648ed7b4 100644 --- a/cmd/clair/config.go +++ b/cmd/clair/config.go @@ -61,6 +61,7 @@ func DefaultConfig() Config { Updater: &clair.UpdaterConfig{ EnabledUpdaters: vulnsrc.ListUpdaters(), Interval: 1 * time.Hour, + SourceURLs: make(map[string]string), }, Worker: &clair.WorkerConfig{ EnabledDetectors: featurens.ListDetectors(), diff --git a/cmd/clair/main.go b/cmd/clair/main.go index e802cbbd..2f08fd81 100644 --- a/cmd/clair/main.go +++ b/cmd/clair/main.go @@ -126,6 +126,8 @@ func configClairVersion(config *Config) { } clair.EnabledUpdaters = strutil.CompareStringListsInBoth(config.Updater.EnabledUpdaters, updaters) + + clair.SourceURLs = config.Updater.SourceURLs } // Boot starts Clair instance with the provided config. diff --git a/config.yaml.sample b/config.yaml.sample index cb6fd5d3..383ec37d 100644 --- a/config.yaml.sample +++ b/config.yaml.sample @@ -68,6 +68,7 @@ clair: # Frequency the database will be updated with vulnerabilities from the default data sources # The value 0 disables the updater entirely. interval: 2h + enabledupdaters: - debian - ubuntu @@ -75,6 +76,14 @@ clair: - oracle - alpine + # Vulnerability data sources + sourceurls: + alpine: "https://git.alpinelinux.org/cgit/alpine-secdb" + debian: "https://security-tracker.debian.org/tracker/data/json" + oracle: "https://linux.oracle.com/oval/" + rhel: "https://www.redhat.com/security/data/oval/" + ubuntu: "https://launchpad.net/ubuntu-cve-tracker" + notifier: # Number of attempts before the notification is marked as failed to be sent attempts: 3 diff --git a/ext/vulnsrc/alpine/alpine.go b/ext/vulnsrc/alpine/alpine.go index 5b6f46e1..a200f9c6 100644 --- a/ext/vulnsrc/alpine/alpine.go +++ b/ext/vulnsrc/alpine/alpine.go @@ -34,8 +34,9 @@ import ( "github.com/coreos/clair/pkg/commonerr" ) +var secdbGitURL = "https://git.alpinelinux.org/cgit/alpine-secdb" + const ( - secdbGitURL = "https://git.alpinelinux.org/cgit/alpine-secdb" updaterFlag = "alpine-secdbUpdater" nvdURLPrefix = "https://cve.mitre.org/cgi-bin/cvename.cgi?name=" ) @@ -115,6 +116,10 @@ func (u *updater) Clean() { } } +func (u *updater) SetSourceUrl(sourceURL string) { + secdbGitURL = sourceURL +} + type lsFilter int const ( diff --git a/ext/vulnsrc/debian/debian.go b/ext/vulnsrc/debian/debian.go index c0efc37e..0b4d22ac 100644 --- a/ext/vulnsrc/debian/debian.go +++ b/ext/vulnsrc/debian/debian.go @@ -34,8 +34,9 @@ import ( "github.com/coreos/clair/pkg/commonerr" ) +var url = "https://security-tracker.debian.org/tracker/data/json" + const ( - url = "https://security-tracker.debian.org/tracker/data/json" cveURLPrefix = "https://security-tracker.debian.org/tracker" updaterFlag = "debianUpdater" ) @@ -101,6 +102,10 @@ func (u *updater) Update(datastore database.Datastore) (resp vulnsrc.UpdateRespo func (u *updater) Clean() {} +func (u *updater) SetSourceUrl(sourceURL string) { + url = sourceURL +} + func buildResponse(jsonReader io.Reader, latestKnownHash string) (resp vulnsrc.UpdateResponse, err error) { hash := latestKnownHash diff --git a/ext/vulnsrc/driver.go b/ext/vulnsrc/driver.go index 91b28831..23b281fe 100644 --- a/ext/vulnsrc/driver.go +++ b/ext/vulnsrc/driver.go @@ -50,6 +50,9 @@ type Updater interface { // Clean deletes any allocated resources. // It is invoked when Clair stops. Clean() + + // Sets the source of vulnerability data to be used by the updater + SetSourceUrl(string) } // RegisterUpdater makes an Updater available by the provided name. diff --git a/ext/vulnsrc/oracle/oracle.go b/ext/vulnsrc/oracle/oracle.go index 40dcd669..e8a90c13 100644 --- a/ext/vulnsrc/oracle/oracle.go +++ b/ext/vulnsrc/oracle/oracle.go @@ -36,9 +36,10 @@ import ( "github.com/coreos/clair/pkg/commonerr" ) +var ovalURI = "https://linux.oracle.com/oval/" + const ( firstOracle5ELSA = 20070057 - ovalURI = "https://linux.oracle.com/oval/" elsaFilePrefix = "com.oracle.elsa-" updaterFlag = "oracleUpdater" ) @@ -202,6 +203,10 @@ func largest(list []int) (largest int) { func (u *updater) Clean() {} +func (u *updater) SetSourceUrl(sourceURL string) { + ovalURI = sourceURL +} + func parseELSA(ovalReader io.Reader) (vulnerabilities []database.VulnerabilityWithAffected, err error) { // Decode the XML. var ov oval diff --git a/ext/vulnsrc/rhel/rhel.go b/ext/vulnsrc/rhel/rhel.go index f4cbce8f..41420fa0 100644 --- a/ext/vulnsrc/rhel/rhel.go +++ b/ext/vulnsrc/rhel/rhel.go @@ -35,12 +35,13 @@ import ( "github.com/coreos/clair/pkg/commonerr" ) +var ovalURI = "https://www.redhat.com/security/data/oval/" + const ( // Before this RHSA, it deals only with RHEL <= 4. firstRHEL5RHSA = 20070044 firstConsideredRHEL = 5 - ovalURI = "https://www.redhat.com/security/data/oval/" rhsaFilePrefix = "com.redhat.rhsa-" updaterFlag = "rhelUpdater" ) @@ -169,6 +170,10 @@ func (u *updater) Update(datastore database.Datastore) (resp vulnsrc.UpdateRespo func (u *updater) Clean() {} +func (u *updater) SetSourceUrl(sourceURL string) { + ovalURI = sourceURL +} + func parseRHSA(ovalReader io.Reader) (vulnerabilities []database.VulnerabilityWithAffected, err error) { // Decode the XML. var ov oval diff --git a/ext/vulnsrc/ubuntu/ubuntu.go b/ext/vulnsrc/ubuntu/ubuntu.go index 6af0c14c..76cda18d 100644 --- a/ext/vulnsrc/ubuntu/ubuntu.go +++ b/ext/vulnsrc/ubuntu/ubuntu.go @@ -37,11 +37,12 @@ import ( "github.com/coreos/clair/pkg/commonerr" ) +var trackerRepository = "https://launchpad.net/ubuntu-cve-tracker" + const ( - trackerURI = "https://launchpad.net/ubuntu-cve-tracker" - trackerRepository = "https://launchpad.net/ubuntu-cve-tracker" - updaterFlag = "ubuntuUpdater" - cveURL = "http://people.ubuntu.com/~ubuntu-security/cve/%s" + trackerURI = "https://launchpad.net/ubuntu-cve-tracker" + updaterFlag = "ubuntuUpdater" + cveURL = "http://people.ubuntu.com/~ubuntu-security/cve/%s" ) var ( @@ -175,6 +176,10 @@ func (u *updater) Clean() { os.RemoveAll(u.repositoryLocalPath) } +func (u *updater) SetSourceUrl(sourceURL string) { + trackerRepository = sourceURL +} + func (u *updater) pullRepository() (err error) { // Determine whether we should branch or pull. if _, pathExists := os.Stat(u.repositoryLocalPath); u.repositoryLocalPath == "" || os.IsNotExist(pathExists) { diff --git a/updater.go b/updater.go index 792e068b..35be86e6 100644 --- a/updater.go +++ b/updater.go @@ -57,6 +57,9 @@ var ( // EnabledUpdaters contains all updaters to be used for update. EnabledUpdaters []string + + // SourceURLs contains any alternative vulnerability data sources + SourceURLs map[string]string ) func init() { @@ -69,6 +72,7 @@ func init() { type UpdaterConfig struct { EnabledUpdaters []string Interval time.Duration + SourceURLs map[string]string } type vulnerabilityChange struct { @@ -276,6 +280,9 @@ func fetch(datastore database.Datastore) (bool, []database.VulnerabilityWithAffe continue } numUpdaters++ + if url, ok := SourceURLs[n]; ok { + u.SetSourceUrl(url) + } go func(name string, u vulnsrc.Updater) { response, err := u.Update(datastore) if err != nil {