Compare commits
17 Commits
master
...
release-2.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
aa5729df66 | ||
![]() |
a80ca551cf | ||
![]() |
ee1b3ff7f1 | ||
![]() |
af7d890865 | ||
![]() |
8bea33576d | ||
![]() |
5d5c193089 | ||
![]() |
086f92a617 | ||
![]() |
d1cadb4cdc | ||
![]() |
f882e1c210 | ||
![]() |
47450faf88 | ||
![]() |
ad98b97a6d | ||
![]() |
21715797c9 | ||
![]() |
e650d58583 | ||
![]() |
f8a1359a60 | ||
![]() |
b2519a044a | ||
![]() |
2453d67c36 | ||
![]() |
4f8d6bee1e |
@ -12,7 +12,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
FROM golang:1.8-alpine
|
FROM golang:1.10-alpine
|
||||||
|
|
||||||
VOLUME /config
|
VOLUME /config
|
||||||
EXPOSE 6060 6061
|
EXPOSE 6060 6061
|
||||||
@ -20,7 +20,7 @@ EXPOSE 6060 6061
|
|||||||
ADD . /go/src/github.com/coreos/clair/
|
ADD . /go/src/github.com/coreos/clair/
|
||||||
WORKDIR /go/src/github.com/coreos/clair/
|
WORKDIR /go/src/github.com/coreos/clair/
|
||||||
|
|
||||||
RUN apk add --no-cache git bzr rpm xz && \
|
RUN apk add --no-cache git rpm xz && \
|
||||||
go install -v github.com/coreos/clair/cmd/clair && \
|
go install -v github.com/coreos/clair/cmd/clair && \
|
||||||
mv /go/bin/clair /clair && \
|
mv /go/bin/clair /clair && \
|
||||||
rm -rf /go /usr/local/go
|
rm -rf /go /usr/local/go
|
||||||
|
@ -119,14 +119,12 @@ To build Clair, you need to latest stable version of [Go] and a working [Go envi
|
|||||||
In addition, Clair requires some additional binaries be installed on the system [$PATH] as runtime dependencies:
|
In addition, Clair requires some additional binaries be installed on the system [$PATH] as runtime dependencies:
|
||||||
|
|
||||||
* [git]
|
* [git]
|
||||||
* [bzr]
|
|
||||||
* [rpm]
|
* [rpm]
|
||||||
* [xz]
|
* [xz]
|
||||||
|
|
||||||
[Go]: https://github.com/golang/go/releases
|
[Go]: https://github.com/golang/go/releases
|
||||||
[Go environment]: https://golang.org/doc/code.html
|
[Go environment]: https://golang.org/doc/code.html
|
||||||
[git]: https://git-scm.com
|
[git]: https://git-scm.com
|
||||||
[bzr]: http://bazaar.canonical.com/en
|
|
||||||
[rpm]: http://www.rpm.org
|
[rpm]: http://www.rpm.org
|
||||||
[xz]: http://tukaani.org/xz
|
[xz]: http://tukaani.org/xz
|
||||||
[$PATH]: https://en.wikipedia.org/wiki/PATH_(variable)
|
[$PATH]: https://en.wikipedia.org/wiki/PATH_(variable)
|
||||||
|
@ -127,7 +127,7 @@ func main() {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// Check for dependencies.
|
// Check for dependencies.
|
||||||
for _, bin := range []string{"git", "bzr", "rpm", "xz"} {
|
for _, bin := range []string{"git", "rpm", "xz"} {
|
||||||
_, err := exec.LookPath(bin)
|
_, err := exec.LookPath(bin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).WithField("dependency", bin).Fatal("failed to find dependency")
|
log.WithError(err).WithField("dependency", bin).Fatal("failed to find dependency")
|
||||||
|
@ -15,13 +15,16 @@
|
|||||||
# The values specified here are the default values that Clair uses if no configuration file is specified or if the keys are not defined.
|
# The values specified here are the default values that Clair uses if no configuration file is specified or if the keys are not defined.
|
||||||
clair:
|
clair:
|
||||||
database:
|
database:
|
||||||
|
# Database driver
|
||||||
|
type: pgsql
|
||||||
|
options:
|
||||||
# PostgreSQL Connection string
|
# PostgreSQL Connection string
|
||||||
# http://www.postgresql.org/docs/9.4/static/libpq-connect.html
|
# https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
|
||||||
source: postgres://postgres:password@postgres:5432/postgres?sslmode=disable
|
source: postgres://postgres:password@postgres:5432/postgres?sslmode=disable
|
||||||
|
|
||||||
# Number of elements kept in the cache
|
# Number of elements kept in the cache
|
||||||
# Values unlikely to change (e.g. namespaces) are cached in order to save prevent needless roundtrips to the database.
|
# Values unlikely to change (e.g. namespaces) are cached in order to save prevent needless roundtrips to the database.
|
||||||
cacheSize: 16384
|
cachesize: 16384
|
||||||
|
|
||||||
api:
|
api:
|
||||||
# API server port
|
# API server port
|
||||||
@ -37,7 +40,7 @@ clair:
|
|||||||
# 32-bit URL-safe base64 key used to encrypt pagination tokens
|
# 32-bit URL-safe base64 key used to encrypt pagination tokens
|
||||||
# If one is not provided, it will be generated.
|
# If one is not provided, it will be generated.
|
||||||
# Multiple clair instances in the same cluster need the same value.
|
# Multiple clair instances in the same cluster need the same value.
|
||||||
paginationKey:
|
paginationkey:
|
||||||
|
|
||||||
# Optional PKI configuration
|
# Optional PKI configuration
|
||||||
# If you want to easily generate client certificates and CAs, try the following projects:
|
# If you want to easily generate client certificates and CAs, try the following projects:
|
||||||
@ -58,7 +61,7 @@ clair:
|
|||||||
attempts: 3
|
attempts: 3
|
||||||
|
|
||||||
# Duration before a failed notification is retried
|
# Duration before a failed notification is retried
|
||||||
renotifyInterval: 2h
|
renotifyinterval: 2h
|
||||||
|
|
||||||
http:
|
http:
|
||||||
# Optional endpoint that will receive notifications via POST requests
|
# Optional endpoint that will receive notifications via POST requests
|
||||||
@ -72,3 +75,6 @@ clair:
|
|||||||
cafile:
|
cafile:
|
||||||
keyfile:
|
keyfile:
|
||||||
certfile:
|
certfile:
|
||||||
|
|
||||||
|
# Optional HTTP Proxy: must be a valid URL (including the scheme).
|
||||||
|
proxy:
|
||||||
|
@ -21,12 +21,14 @@ var DebianReleasesMapping = map[string]string{
|
|||||||
"wheezy": "7",
|
"wheezy": "7",
|
||||||
"jessie": "8",
|
"jessie": "8",
|
||||||
"stretch": "9",
|
"stretch": "9",
|
||||||
|
"buster": "10",
|
||||||
"sid": "unstable",
|
"sid": "unstable",
|
||||||
|
|
||||||
// Class names
|
// Class names
|
||||||
"oldstable": "7",
|
"oldoldstable": "7",
|
||||||
"stable": "8",
|
"oldstable": "8",
|
||||||
"testing": "9",
|
"stable": "9",
|
||||||
|
"testing": "10",
|
||||||
"unstable": "unstable",
|
"unstable": "unstable",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,4 +45,5 @@ var UbuntuReleasesMapping = map[string]string{
|
|||||||
"yakkety": "16.10",
|
"yakkety": "16.10",
|
||||||
"zesty": "17.04",
|
"zesty": "17.04",
|
||||||
"artful": "17.10",
|
"artful": "17.10",
|
||||||
|
"bionic": "18.04",
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,8 @@ func (d detector) Detect(files tarutil.FilesMap) (*database.Namespace, error) {
|
|||||||
OS = "debian"
|
OS = "debian"
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
line[2] = strings.Split(line[2], "/")[0]
|
||||||
version, found = database.UbuntuReleasesMapping[line[2]]
|
version, found = database.UbuntuReleasesMapping[line[2]]
|
||||||
if found {
|
if found {
|
||||||
OS = "ubuntu"
|
OS = "ubuntu"
|
||||||
|
@ -30,7 +30,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
oracleReleaseRegexp = regexp.MustCompile(`(?P<os>[^\s]*) (Linux Server release) (?P<version>[\d]+)`)
|
oracleReleaseRegexp = regexp.MustCompile(`(?P<os>Oracle) (Linux Server release) (?P<version>[\d]+)`)
|
||||||
centosReleaseRegexp = regexp.MustCompile(`(?P<os>[^\s]*) (Linux release|release) (?P<version>[\d]+)`)
|
centosReleaseRegexp = regexp.MustCompile(`(?P<os>[^\s]*) (Linux release|release) (?P<version>[\d]+)`)
|
||||||
redhatReleaseRegexp = regexp.MustCompile(`(?P<os>Red Hat Enterprise Linux) (Client release|Server release|Workstation release) (?P<version>[\d]+)`)
|
redhatReleaseRegexp = regexp.MustCompile(`(?P<os>Red Hat Enterprise Linux) (Client release|Server release|Workstation release) (?P<version>[\d]+)`)
|
||||||
)
|
)
|
||||||
|
@ -42,6 +42,12 @@ func TestDetector(t *testing.T) {
|
|||||||
"etc/centos-release": []byte(`CentOS release 6.6 (Final)`),
|
"etc/centos-release": []byte(`CentOS release 6.6 (Final)`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ExpectedNamespace: &database.Namespace{Name: "centos:7"},
|
||||||
|
Files: tarutil.FilesMap{
|
||||||
|
"etc/redhat-release": []byte(`Red Hat Enterprise Linux Server release 7.2 (Maipo)`),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ExpectedNamespace: &database.Namespace{Name: "centos:7"},
|
ExpectedNamespace: &database.Namespace{Name: "centos:7"},
|
||||||
Files: tarutil.FilesMap{
|
Files: tarutil.FilesMap{
|
||||||
|
@ -122,6 +122,7 @@ func Extract(format, path string, headers map[string]string, toExtract []string)
|
|||||||
// Send the request and handle the response.
|
// Send the request and handle the response.
|
||||||
tr := &http.Transport{
|
tr := &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecureTLS},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecureTLS},
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
}
|
}
|
||||||
client := &http.Client{Transport: tr}
|
client := &http.Client{Transport: tr}
|
||||||
r, err := client.Do(request)
|
r, err := client.Do(request)
|
||||||
|
@ -38,8 +38,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
dataFeedURL string = "http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%s.xml.gz"
|
dataFeedURL string = "https://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%s.xml.gz"
|
||||||
dataFeedMetaURL string = "http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%s.meta"
|
dataFeedMetaURL string = "https://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%s.meta"
|
||||||
|
|
||||||
appenderName string = "NVD"
|
appenderName string = "NVD"
|
||||||
|
|
||||||
|
@ -18,14 +18,12 @@ package ubuntu
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -38,8 +36,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
trackerURI = "https://launchpad.net/ubuntu-cve-tracker"
|
trackerGitURL = "https://git.launchpad.net/ubuntu-cve-tracker"
|
||||||
trackerRepository = "https://launchpad.net/ubuntu-cve-tracker"
|
|
||||||
updaterFlag = "ubuntuUpdater"
|
updaterFlag = "ubuntuUpdater"
|
||||||
cveURL = "http://people.ubuntu.com/~ubuntu-security/cve/%s"
|
cveURL = "http://people.ubuntu.com/~ubuntu-security/cve/%s"
|
||||||
)
|
)
|
||||||
@ -87,25 +84,27 @@ func init() {
|
|||||||
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.WithField("package", "Ubuntu").Info("Start fetching vulnerabilities")
|
log.WithField("package", "Ubuntu").Info("Start fetching vulnerabilities")
|
||||||
|
|
||||||
// Pull the bzr repository.
|
// Pull the master branch.
|
||||||
if err = u.pullRepository(); err != nil {
|
var commit string
|
||||||
return resp, err
|
commit, err = u.pullRepository()
|
||||||
}
|
|
||||||
|
|
||||||
// Get revision number.
|
|
||||||
revisionNumber, err := getRevisionNumber(u.repositoryLocalPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return resp, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the latest revision number we successfully applied in the database.
|
// Get the latest revision number we successfully applied in the database.
|
||||||
dbRevisionNumber, err := datastore.GetKeyValue("ubuntuUpdater")
|
dbCommit, err := datastore.GetKeyValue(updaterFlag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Short-circuit if there have been no updates.
|
||||||
|
if commit == dbCommit {
|
||||||
|
log.WithField("package", "ubuntu").Debug("no update")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get the list of vulnerabilities that we have to update.
|
// Get the list of vulnerabilities that we have to update.
|
||||||
modifiedCVE, err := collectModifiedVulnerabilities(revisionNumber, dbRevisionNumber, u.repositoryLocalPath)
|
modifiedCVE, err := collectModifiedVulnerabilities(u.repositoryLocalPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
@ -136,8 +135,7 @@ func (u *updater) Update(datastore database.Datastore) (resp vulnsrc.UpdateRespo
|
|||||||
|
|
||||||
// If we encountered unknown Ubuntu release, we don't want the revision
|
// If we encountered unknown Ubuntu release, we don't want the revision
|
||||||
// number to be considered as managed.
|
// number to be considered as managed.
|
||||||
dbRevisionNumberInt, _ := strconv.Atoi(dbRevisionNumber)
|
commit = dbCommit
|
||||||
revisionNumber = dbRevisionNumberInt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the file manually.
|
// Close the file manually.
|
||||||
@ -150,7 +148,7 @@ func (u *updater) Update(datastore database.Datastore) (resp vulnsrc.UpdateRespo
|
|||||||
|
|
||||||
// Add flag and notes.
|
// Add flag and notes.
|
||||||
resp.FlagName = updaterFlag
|
resp.FlagName = updaterFlag
|
||||||
resp.FlagValue = strconv.Itoa(revisionNumber)
|
resp.FlagValue = commit
|
||||||
for note := range notes {
|
for note := range notes {
|
||||||
resp.Notes = append(resp.Notes, note)
|
resp.Notes = append(resp.Notes, note)
|
||||||
}
|
}
|
||||||
@ -162,60 +160,45 @@ func (u *updater) Clean() {
|
|||||||
os.RemoveAll(u.repositoryLocalPath)
|
os.RemoveAll(u.repositoryLocalPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *updater) pullRepository() (err error) {
|
func (u *updater) pullRepository() (commit string, err error) {
|
||||||
// Determine whether we should branch or pull.
|
// If the repository doesn't exist, clone it.
|
||||||
if _, pathExists := os.Stat(u.repositoryLocalPath); u.repositoryLocalPath == "" || os.IsNotExist(pathExists) {
|
if _, pathExists := os.Stat(u.repositoryLocalPath); u.repositoryLocalPath == "" || os.IsNotExist(pathExists) {
|
||||||
// Create a temporary folder to store the repository.
|
|
||||||
if u.repositoryLocalPath, err = ioutil.TempDir(os.TempDir(), "ubuntu-cve-tracker"); err != nil {
|
if u.repositoryLocalPath, err = ioutil.TempDir(os.TempDir(), "ubuntu-cve-tracker"); err != nil {
|
||||||
return vulnsrc.ErrFilesystem
|
return "", vulnsrc.ErrFilesystem
|
||||||
}
|
}
|
||||||
|
|
||||||
// Branch repository.
|
cmd := exec.Command("git", "clone", trackerGitURL, ".")
|
||||||
cmd := exec.Command("bzr", "branch", "--use-existing-dir", trackerRepository, ".")
|
|
||||||
cmd.Dir = u.repositoryLocalPath
|
cmd.Dir = u.repositoryLocalPath
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
log.WithError(err).WithField("output", string(out)).Error("could not branch Ubuntu repository")
|
u.Clean()
|
||||||
return commonerr.ErrCouldNotDownload
|
log.WithError(err).WithField("output", string(out)).Error("could not pull ubuntu-cve-tracker repository")
|
||||||
|
return "", commonerr.ErrCouldNotDownload
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
return nil
|
// The repository already exists and it needs to be refreshed via a pull.
|
||||||
}
|
cmd := exec.Command("git", "pull")
|
||||||
|
|
||||||
// Pull repository.
|
|
||||||
cmd := exec.Command("bzr", "pull", "--overwrite")
|
|
||||||
cmd.Dir = u.repositoryLocalPath
|
cmd.Dir = u.repositoryLocalPath
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
if _, err := cmd.CombinedOutput(); err != nil {
|
||||||
os.RemoveAll(u.repositoryLocalPath)
|
return "", vulnsrc.ErrGitFailure
|
||||||
log.WithError(err).WithField("output", string(out)).Error("could not pull Ubuntu repository")
|
}
|
||||||
return commonerr.ErrCouldNotDownload
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
cmd := exec.Command("git", "rev-parse", "HEAD")
|
||||||
}
|
cmd.Dir = u.repositoryLocalPath
|
||||||
|
|
||||||
func getRevisionNumber(pathToRepo string) (int, error) {
|
|
||||||
cmd := exec.Command("bzr", "revno")
|
|
||||||
cmd.Dir = pathToRepo
|
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).WithField("output", string(out)).Error("could not get Ubuntu repository's revision number")
|
return "", vulnsrc.ErrGitFailure
|
||||||
return 0, commonerr.ErrCouldNotDownload
|
|
||||||
}
|
}
|
||||||
|
|
||||||
revno, err := strconv.Atoi(strings.TrimSpace(string(out)))
|
commit = strings.TrimSpace(string(out))
|
||||||
if err != nil {
|
return
|
||||||
log.WithError(err).WithField("output", string(out)).Error("could not parse Ubuntu repository's revision number")
|
|
||||||
return 0, commonerr.ErrCouldNotDownload
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return revno, nil
|
func collectModifiedVulnerabilities(repositoryLocalPath string) (map[string]struct{}, error) {
|
||||||
}
|
|
||||||
|
|
||||||
func collectModifiedVulnerabilities(revision int, dbRevision, repositoryLocalPath string) (map[string]struct{}, error) {
|
|
||||||
modifiedCVE := make(map[string]struct{})
|
modifiedCVE := make(map[string]struct{})
|
||||||
|
|
||||||
// Handle a brand new database.
|
// Handle a brand new database.
|
||||||
if dbRevision == "" {
|
|
||||||
for _, folder := range []string{"active", "retired"} {
|
for _, folder := range []string{"active", "retired"} {
|
||||||
d, err := os.Open(repositoryLocalPath + "/" + folder)
|
d, err := os.Open(repositoryLocalPath + "/" + folder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -246,36 +229,7 @@ func collectModifiedVulnerabilities(revision int, dbRevision, repositoryLocalPat
|
|||||||
}
|
}
|
||||||
|
|
||||||
return modifiedCVE, nil
|
return modifiedCVE, nil
|
||||||
}
|
|
||||||
|
|
||||||
// Handle an up to date database.
|
|
||||||
dbRevisionInt, _ := strconv.Atoi(dbRevision)
|
|
||||||
if revision == dbRevisionInt {
|
|
||||||
log.WithField("package", "Ubuntu").Debug("no update")
|
|
||||||
return modifiedCVE, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle a database that needs upgrading.
|
|
||||||
cmd := exec.Command("bzr", "log", "--verbose", "-r"+strconv.Itoa(dbRevisionInt+1)+"..", "-n0")
|
|
||||||
cmd.Dir = repositoryLocalPath
|
|
||||||
out, err := cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).WithField("output", string(out)).Error("could not get Ubuntu vulnerabilities repository logs")
|
|
||||||
return nil, commonerr.ErrCouldNotDownload
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(bytes.NewReader(out))
|
|
||||||
for scanner.Scan() {
|
|
||||||
text := strings.TrimSpace(scanner.Text())
|
|
||||||
if strings.Contains(text, "CVE-") && (strings.HasPrefix(text, "active/") || strings.HasPrefix(text, "retired/")) {
|
|
||||||
if strings.Contains(text, " => ") {
|
|
||||||
text = text[strings.Index(text, " => ")+4:]
|
|
||||||
}
|
|
||||||
modifiedCVE[text] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return modifiedCVE, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseUbuntuCVE(fileContent io.Reader) (vulnerability database.Vulnerability, unknownReleases map[string]struct{}, err error) {
|
func parseUbuntuCVE(fileContent io.Reader) (vulnerability database.Vulnerability, unknownReleases map[string]struct{}, err error) {
|
||||||
@ -344,6 +298,7 @@ func parseUbuntuCVE(fileContent io.Reader) (vulnerability database.Vulnerability
|
|||||||
// Only consider the package if its status is needed, active, deferred, not-affected or
|
// Only consider the package if its status is needed, active, deferred, not-affected or
|
||||||
// released. Ignore DNE (package does not exist), needs-triage, ignored, pending.
|
// released. Ignore DNE (package does not exist), needs-triage, ignored, pending.
|
||||||
if md["status"] == "needed" || md["status"] == "active" || md["status"] == "deferred" || md["status"] == "released" || md["status"] == "not-affected" {
|
if md["status"] == "needed" || md["status"] == "active" || md["status"] == "deferred" || md["status"] == "released" || md["status"] == "not-affected" {
|
||||||
|
md["release"] = strings.Split(md["release"], "/")[0]
|
||||||
if _, isReleaseIgnored := ubuntuIgnoredReleases[md["release"]]; isReleaseIgnored {
|
if _, isReleaseIgnored := ubuntuIgnoredReleases[md["release"]]; isReleaseIgnored {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -392,7 +347,7 @@ func parseUbuntuCVE(fileContent io.Reader) (vulnerability database.Vulnerability
|
|||||||
|
|
||||||
// If no link has been provided (CVE-2006-NNN0 for instance), add the link to the tracker
|
// If no link has been provided (CVE-2006-NNN0 for instance), add the link to the tracker
|
||||||
if vulnerability.Link == "" {
|
if vulnerability.Link == "" {
|
||||||
vulnerability.Link = trackerURI
|
vulnerability.Link = trackerGitURL
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no priority has been provided (CVE-2007-0667 for instance), set the priority to Unknown
|
// If no priority has been provided (CVE-2007-0667 for instance), set the priority to Unknown
|
||||||
|
29
updater.go
29
updater.go
@ -35,6 +35,7 @@ const (
|
|||||||
updaterLockName = "updater"
|
updaterLockName = "updater"
|
||||||
updaterLockDuration = updaterLockRefreshDuration + time.Minute*2
|
updaterLockDuration = updaterLockRefreshDuration + time.Minute*2
|
||||||
updaterLockRefreshDuration = time.Minute * 8
|
updaterLockRefreshDuration = time.Minute * 8
|
||||||
|
updaterSleepBetweenLoopsDuration = time.Minute
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -124,7 +125,14 @@ func RunUpdater(config *UpdaterConfig, datastore database.Datastore, st *stopper
|
|||||||
if stop {
|
if stop {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sleep for a short duration to prevent pinning the CPU on a
|
||||||
|
// consistent failure.
|
||||||
|
if stopped := sleepUpdater(time.Now().Add(updaterSleepBetweenLoopsDuration), st); stopped {
|
||||||
|
break
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
lockOwner, lockExpiration, err := datastore.FindLock(updaterLockName)
|
lockOwner, lockExpiration, err := datastore.FindLock(updaterLockName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -137,16 +145,10 @@ func RunUpdater(config *UpdaterConfig, datastore database.Datastore, st *stopper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sleep, but remain stoppable until approximately the next update time.
|
if stopped := sleepUpdater(nextUpdate, st); stopped {
|
||||||
now := time.Now().UTC()
|
|
||||||
waitUntil := nextUpdate.Add(time.Duration(rand.ExpFloat64()/0.5) * time.Second)
|
|
||||||
log.WithField("scheduled time", waitUntil).Debug("next update attempt scheduled")
|
|
||||||
if !waitUntil.Before(now) {
|
|
||||||
if !st.Sleep(waitUntil.Sub(time.Now())) {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Clean resources.
|
// Clean resources.
|
||||||
for _, appenders := range vulnmdsrc.Appenders() {
|
for _, appenders := range vulnmdsrc.Appenders() {
|
||||||
@ -159,6 +161,19 @@ func RunUpdater(config *UpdaterConfig, datastore database.Datastore, st *stopper
|
|||||||
log.Info("updater service stopped")
|
log.Info("updater service stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sleepUpdater sleeps the updater for an approximate duration, but remains
|
||||||
|
// able to be cancelled by a stopper.
|
||||||
|
func sleepUpdater(approxWakeup time.Time, st *stopper.Stopper) (stopped bool) {
|
||||||
|
waitUntil := approxWakeup.Add(time.Duration(rand.ExpFloat64()/0.5) * time.Second)
|
||||||
|
log.WithField("scheduled time", waitUntil).Debug("updater sleeping")
|
||||||
|
if !waitUntil.Before(time.Now().UTC()) {
|
||||||
|
if !st.Sleep(waitUntil.Sub(time.Now())) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// update fetches all the vulnerabilities from the registered fetchers, upserts
|
// update fetches all the vulnerabilities from the registered fetchers, upserts
|
||||||
// them into the database and then sends notifications.
|
// them into the database and then sends notifications.
|
||||||
func update(datastore database.Datastore, firstUpdate bool) {
|
func update(datastore database.Datastore, firstUpdate bool) {
|
||||||
|
Loading…
Reference in New Issue
Block a user