clair: mv updater clair and mv severity to db
This commit is contained in:
parent
6e8e6ad26b
commit
9c63a63944
@ -24,7 +24,6 @@ import (
|
|||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
"github.com/fernet/fernet-go"
|
"github.com/fernet/fernet-go"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt"
|
"github.com/coreos/clair/ext/versionfmt"
|
||||||
)
|
)
|
||||||
@ -109,7 +108,7 @@ type Vulnerability struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v Vulnerability) DatabaseModel() (database.Vulnerability, error) {
|
func (v Vulnerability) DatabaseModel() (database.Vulnerability, error) {
|
||||||
severity, err := clair.NewSeverity(v.Severity)
|
severity, err := database.NewSeverity(v.Severity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return database.Vulnerability{}, err
|
return database.Vulnerability{}, err
|
||||||
}
|
}
|
||||||
|
@ -27,13 +27,13 @@ import (
|
|||||||
|
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
|
||||||
|
"github.com/coreos/clair"
|
||||||
"github.com/coreos/clair/api"
|
"github.com/coreos/clair/api"
|
||||||
"github.com/coreos/clair/api/context"
|
"github.com/coreos/clair/api/context"
|
||||||
"github.com/coreos/clair/config"
|
"github.com/coreos/clair/config"
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/notifier"
|
"github.com/coreos/clair/notifier"
|
||||||
"github.com/coreos/clair/pkg/stopper"
|
"github.com/coreos/clair/pkg/stopper"
|
||||||
"github.com/coreos/clair/updater"
|
|
||||||
|
|
||||||
// Register database driver.
|
// Register database driver.
|
||||||
_ "github.com/coreos/clair/database/pgsql"
|
_ "github.com/coreos/clair/database/pgsql"
|
||||||
@ -112,7 +112,7 @@ func Boot(config *config.Config) {
|
|||||||
|
|
||||||
// Start updater
|
// Start updater
|
||||||
st.Begin()
|
st.Begin()
|
||||||
go updater.Run(config.Updater, db, st)
|
go clair.RunUpdater(config.Updater, db, st)
|
||||||
|
|
||||||
// Wait for interruption and shutdown gracefully.
|
// Wait for interruption and shutdown gracefully.
|
||||||
waitForSignals(syscall.SIGINT, syscall.SIGTERM)
|
waitForSignals(syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
// Package database defines the Clair's models and a common interface for database implementations.
|
// Package database defines the Clair's models and a common interface for
|
||||||
|
// database implementations.
|
||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -144,7 +145,8 @@ type Datastore interface {
|
|||||||
// Vulnerability in the database. It can be used to store the fact that a
|
// Vulnerability in the database. It can be used to store the fact that a
|
||||||
// Vulnerability no longer affects the given Feature in any Version.
|
// Vulnerability no longer affects the given Feature in any Version.
|
||||||
//
|
//
|
||||||
// It has has to create a Notification that will contain the old and the updated Vulnerability.
|
// It has has to create a Notification that will contain the old and the
|
||||||
|
// updated Vulnerability.
|
||||||
DeleteVulnerabilityFix(vulnerabilityNamespace, vulnerabilityName, featureName string) error
|
DeleteVulnerabilityFix(vulnerabilityNamespace, vulnerabilityName, featureName string) error
|
||||||
|
|
||||||
// GetAvailableNotification returns the Name, Created, Notified and Deleted
|
// GetAvailableNotification returns the Name, Created, Notified and Deleted
|
||||||
|
@ -18,8 +18,6 @@ import (
|
|||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ID is only meant to be used by database implementations and should never be used for anything else.
|
// ID is only meant to be used by database implementations and should never be used for anything else.
|
||||||
@ -70,7 +68,7 @@ type Vulnerability struct {
|
|||||||
|
|
||||||
Description string
|
Description string
|
||||||
Link string
|
Link string
|
||||||
Severity clair.Severity
|
Severity Severity
|
||||||
|
|
||||||
Metadata MetadataMap
|
Metadata MetadataMap
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ import (
|
|||||||
"github.com/pborman/uuid"
|
"github.com/pborman/uuid"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
||||||
)
|
)
|
||||||
@ -92,7 +91,7 @@ func TestRaceAffects(t *testing.T) {
|
|||||||
Version: strconv.Itoa(version),
|
Version: strconv.Itoa(version),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Severity: clair.Unknown,
|
Severity: database.UnknownSeverity,
|
||||||
}
|
}
|
||||||
|
|
||||||
vulnerabilities[version] = append(vulnerabilities[version], vulnerability)
|
vulnerabilities[version] = append(vulnerabilities[version], vulnerability)
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
||||||
"github.com/coreos/clair/pkg/commonerr"
|
"github.com/coreos/clair/pkg/commonerr"
|
||||||
@ -91,7 +90,7 @@ func TestFindLayer(t *testing.T) {
|
|||||||
if assert.Len(t, featureVersion.AffectedBy, 1) {
|
if assert.Len(t, featureVersion.AffectedBy, 1) {
|
||||||
assert.Equal(t, "debian:7", featureVersion.AffectedBy[0].Namespace.Name)
|
assert.Equal(t, "debian:7", featureVersion.AffectedBy[0].Namespace.Name)
|
||||||
assert.Equal(t, "CVE-OPENSSL-1-DEB7", featureVersion.AffectedBy[0].Name)
|
assert.Equal(t, "CVE-OPENSSL-1-DEB7", featureVersion.AffectedBy[0].Name)
|
||||||
assert.Equal(t, clair.High, featureVersion.AffectedBy[0].Severity)
|
assert.Equal(t, database.HighSeverity, featureVersion.AffectedBy[0].Severity)
|
||||||
assert.Equal(t, "A vulnerability affecting OpenSSL < 2.0 on Debian 7.0", featureVersion.AffectedBy[0].Description)
|
assert.Equal(t, "A vulnerability affecting OpenSSL < 2.0 on Debian 7.0", featureVersion.AffectedBy[0].Description)
|
||||||
assert.Equal(t, "http://google.com/#q=CVE-OPENSSL-1-DEB7", featureVersion.AffectedBy[0].Link)
|
assert.Equal(t, "http://google.com/#q=CVE-OPENSSL-1-DEB7", featureVersion.AffectedBy[0].Link)
|
||||||
assert.Equal(t, "2.0", featureVersion.AffectedBy[0].FixedBy)
|
assert.Equal(t, "2.0", featureVersion.AffectedBy[0].FixedBy)
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt"
|
"github.com/coreos/clair/ext/versionfmt"
|
||||||
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
||||||
@ -169,7 +168,7 @@ func TestNotification(t *testing.T) {
|
|||||||
|
|
||||||
// Update a vulnerability and ensure that the old/new vulnerabilities are correct.
|
// Update a vulnerability and ensure that the old/new vulnerabilities are correct.
|
||||||
v1b := v1
|
v1b := v1
|
||||||
v1b.Severity = clair.High
|
v1b.Severity = database.HighSeverity
|
||||||
v1b.FixedIn = []database.FeatureVersion{
|
v1b.FixedIn = []database.FeatureVersion{
|
||||||
{
|
{
|
||||||
Feature: f1,
|
Feature: f1,
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt"
|
"github.com/coreos/clair/ext/versionfmt"
|
||||||
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
||||||
@ -44,7 +43,7 @@ func TestFindVulnerability(t *testing.T) {
|
|||||||
Name: "CVE-OPENSSL-1-DEB7",
|
Name: "CVE-OPENSSL-1-DEB7",
|
||||||
Description: "A vulnerability affecting OpenSSL < 2.0 on Debian 7.0",
|
Description: "A vulnerability affecting OpenSSL < 2.0 on Debian 7.0",
|
||||||
Link: "http://google.com/#q=CVE-OPENSSL-1-DEB7",
|
Link: "http://google.com/#q=CVE-OPENSSL-1-DEB7",
|
||||||
Severity: clair.High,
|
Severity: database.HighSeverity,
|
||||||
Namespace: database.Namespace{
|
Namespace: database.Namespace{
|
||||||
Name: "debian:7",
|
Name: "debian:7",
|
||||||
VersionFormat: dpkg.ParserName,
|
VersionFormat: dpkg.ParserName,
|
||||||
@ -74,7 +73,7 @@ func TestFindVulnerability(t *testing.T) {
|
|||||||
Name: "debian:7",
|
Name: "debian:7",
|
||||||
VersionFormat: dpkg.ParserName,
|
VersionFormat: dpkg.ParserName,
|
||||||
},
|
},
|
||||||
Severity: clair.Unknown,
|
Severity: database.UnknownSeverity,
|
||||||
}
|
}
|
||||||
|
|
||||||
v2f, err := datastore.FindVulnerability("debian:7", "CVE-NOPE")
|
v2f, err := datastore.FindVulnerability("debian:7", "CVE-NOPE")
|
||||||
@ -180,13 +179,13 @@ func TestInsertVulnerability(t *testing.T) {
|
|||||||
Name: "",
|
Name: "",
|
||||||
Namespace: n1,
|
Namespace: n1,
|
||||||
FixedIn: []database.FeatureVersion{f1},
|
FixedIn: []database.FeatureVersion{f1},
|
||||||
Severity: clair.Unknown,
|
Severity: database.UnknownSeverity,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "TestInsertVulnerability0",
|
Name: "TestInsertVulnerability0",
|
||||||
Namespace: database.Namespace{},
|
Namespace: database.Namespace{},
|
||||||
FixedIn: []database.FeatureVersion{f1},
|
FixedIn: []database.FeatureVersion{f1},
|
||||||
Severity: clair.Unknown,
|
Severity: database.UnknownSeverity,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "TestInsertVulnerability0-",
|
Name: "TestInsertVulnerability0-",
|
||||||
@ -197,7 +196,7 @@ func TestInsertVulnerability(t *testing.T) {
|
|||||||
Name: "TestInsertVulnerability0",
|
Name: "TestInsertVulnerability0",
|
||||||
Namespace: n1,
|
Namespace: n1,
|
||||||
FixedIn: []database.FeatureVersion{f2},
|
FixedIn: []database.FeatureVersion{f2},
|
||||||
Severity: clair.Unknown,
|
Severity: database.UnknownSeverity,
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
err := datastore.InsertVulnerabilities([]database.Vulnerability{vulnerability}, true)
|
err := datastore.InsertVulnerabilities([]database.Vulnerability{vulnerability}, true)
|
||||||
@ -217,7 +216,7 @@ func TestInsertVulnerability(t *testing.T) {
|
|||||||
Name: "TestInsertVulnerability1",
|
Name: "TestInsertVulnerability1",
|
||||||
Namespace: n1,
|
Namespace: n1,
|
||||||
FixedIn: []database.FeatureVersion{f1, f3, f6, f7},
|
FixedIn: []database.FeatureVersion{f1, f3, f6, f7},
|
||||||
Severity: clair.Low,
|
Severity: database.LowSeverity,
|
||||||
Description: "TestInsertVulnerabilityDescription1",
|
Description: "TestInsertVulnerabilityDescription1",
|
||||||
Link: "TestInsertVulnerabilityLink1",
|
Link: "TestInsertVulnerabilityLink1",
|
||||||
Metadata: v1meta,
|
Metadata: v1meta,
|
||||||
@ -233,7 +232,7 @@ func TestInsertVulnerability(t *testing.T) {
|
|||||||
// Update vulnerability.
|
// Update vulnerability.
|
||||||
v1.Description = "TestInsertVulnerabilityLink2"
|
v1.Description = "TestInsertVulnerabilityLink2"
|
||||||
v1.Link = "TestInsertVulnerabilityLink2"
|
v1.Link = "TestInsertVulnerabilityLink2"
|
||||||
v1.Severity = clair.High
|
v1.Severity = database.HighSeverity
|
||||||
// Update f3 in f4, add fixed in f5, add fixed in f6 which already exists,
|
// Update f3 in f4, add fixed in f5, add fixed in f6 which already exists,
|
||||||
// removes fixed in f7 by adding f8 which is f7 but with MinVersion, and
|
// removes fixed in f7 by adding f8 which is f7 but with MinVersion, and
|
||||||
// add fixed by f5 a second time (duplicated).
|
// add fixed by f5 a second time (duplicated).
|
||||||
|
134
database/severity.go
Normal file
134
database/severity.go
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
// Copyright 2017 clair authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql/driver"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrFailedToParseSeverity is the error returned when a severity could not
|
||||||
|
// be parsed from a string.
|
||||||
|
var ErrFailedToParseSeverity = errors.New("failed to parse Severity from input")
|
||||||
|
|
||||||
|
// Severity defines a standard scale for measuring the severity of a
|
||||||
|
// vulnerability.
|
||||||
|
type Severity string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// UnknownSeverity is either a security problem that has not been assigned to
|
||||||
|
// a priority yet or a priority that our system did not recognize.
|
||||||
|
UnknownSeverity Severity = "Unknown"
|
||||||
|
|
||||||
|
// NegligibleSeverity is technically a security problem, but is only
|
||||||
|
// theoretical in nature, requires a very special situation, has almost no
|
||||||
|
// install base, or does no real damage. These tend not to get backport from
|
||||||
|
// upstreams, and will likely not be included in security updates unless
|
||||||
|
// there is an easy fix and some other issue causes an update.
|
||||||
|
NegligibleSeverity Severity = "Negligible"
|
||||||
|
|
||||||
|
// LowSeverity is a security problem, but is hard to exploit due to
|
||||||
|
// environment, requires a user-assisted attack, a small install base, or
|
||||||
|
// does very little damage. These tend to be included in security updates
|
||||||
|
// only when higher priority issues require an update, or if many low
|
||||||
|
// priority issues have built up.
|
||||||
|
LowSeverity Severity = "Low"
|
||||||
|
|
||||||
|
// MediumSeverity is a real security problem, and is exploitable for many
|
||||||
|
// people. Includes network daemon denial of service attacks, cross-site
|
||||||
|
// scripting, and gaining user privileges. Updates should be made soon for
|
||||||
|
// this priority of issue.
|
||||||
|
MediumSeverity Severity = "Medium"
|
||||||
|
|
||||||
|
// HighSeverity is a real problem, exploitable for many people in a default
|
||||||
|
// installation. Includes serious remote denial of services, local root
|
||||||
|
// privilege escalations, or data loss.
|
||||||
|
HighSeverity Severity = "High"
|
||||||
|
|
||||||
|
// CriticalSeverity is a world-burning problem, exploitable for nearly all
|
||||||
|
// people in a default installation of Linux. Includes remote root privilege
|
||||||
|
// escalations, or massive data loss.
|
||||||
|
CriticalSeverity Severity = "Critical"
|
||||||
|
|
||||||
|
// Defcon1Severity is a Critical problem which has been manually highlighted
|
||||||
|
// by the team. It requires an immediate attention.
|
||||||
|
Defcon1Severity Severity = "Defcon1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Severities lists all known severities, ordered from lowest to highest.
|
||||||
|
var Severities = []Severity{
|
||||||
|
UnknownSeverity,
|
||||||
|
NegligibleSeverity,
|
||||||
|
LowSeverity,
|
||||||
|
MediumSeverity,
|
||||||
|
HighSeverity,
|
||||||
|
CriticalSeverity,
|
||||||
|
Defcon1Severity,
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSeverity attempts to parse a string into a standard Severity value.
|
||||||
|
func NewSeverity(s string) (Severity, error) {
|
||||||
|
for _, ss := range Severities {
|
||||||
|
if strings.EqualFold(s, string(ss)) {
|
||||||
|
return ss, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return UnknownSeverity, ErrFailedToParseSeverity
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare determines the equality of two severities.
|
||||||
|
//
|
||||||
|
// If the severities are equal, returns 0.
|
||||||
|
// If the receiever is less, returns -1.
|
||||||
|
// If the receiver is greater, returns 1.
|
||||||
|
func (s Severity) Compare(s2 Severity) int {
|
||||||
|
var i1, i2 int
|
||||||
|
|
||||||
|
for i1 = 0; i1 < len(Severities); i1 = i1 + 1 {
|
||||||
|
if s == Severities[i1] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i2 = 0; i2 < len(Severities); i2 = i2 + 1 {
|
||||||
|
if s2 == Severities[i2] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i1 - i2
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan implements the database/sql.Scanner interface.
|
||||||
|
func (s *Severity) Scan(value interface{}) error {
|
||||||
|
val, ok := value.([]byte)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("could not scan a Severity from a non-string input")
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
*s, err = NewSeverity(string(val))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value implements the database/sql/driver.Valuer interface.
|
||||||
|
func (s Severity) Value() (driver.Value, error) {
|
||||||
|
return string(s), nil
|
||||||
|
}
|
@ -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.
|
||||||
|
|
||||||
package clair
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@ -21,9 +21,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestCompareSeverity(t *testing.T) {
|
func TestCompareSeverity(t *testing.T) {
|
||||||
assert.Equal(t, Medium.Compare(Medium), 0, "Severity comparison failed")
|
assert.Equal(t, MediumSeverity.Compare(MediumSeverity), 0, "Severity comparison failed")
|
||||||
assert.True(t, Medium.Compare(High) < 0, "Severity comparison failed")
|
assert.True(t, MediumSeverity.Compare(HighSeverity) < 0, "Severity comparison failed")
|
||||||
assert.True(t, Critical.Compare(Low) > 0, "Severity comparison failed")
|
assert.True(t, CriticalSeverity.Compare(LowSeverity) > 0, "Severity comparison failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseSeverity(t *testing.T) {
|
func TestParseSeverity(t *testing.T) {
|
@ -19,7 +19,6 @@ package vulnmdsrc
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -29,7 +28,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AppendFunc is the type of a callback provided to an Appender.
|
// AppendFunc is the type of a callback provided to an Appender.
|
||||||
type AppendFunc func(metadataKey string, metadata interface{}, severity clair.Severity)
|
type AppendFunc func(metadataKey string, metadata interface{}, severity database.Severity)
|
||||||
|
|
||||||
// Appender represents anything that can fetch vulnerability metadata and
|
// Appender represents anything that can fetch vulnerability metadata and
|
||||||
// append it to a Vulnerability.
|
// append it to a Vulnerability.
|
||||||
|
@ -32,7 +32,6 @@ import (
|
|||||||
|
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/vulnmdsrc"
|
"github.com/coreos/clair/ext/vulnmdsrc"
|
||||||
"github.com/coreos/clair/pkg/commonerr"
|
"github.com/coreos/clair/pkg/commonerr"
|
||||||
@ -218,23 +217,25 @@ func getHashFromMetaURL(metaURL string) (string, error) {
|
|||||||
return "", errors.New("invalid .meta file format")
|
return "", errors.New("invalid .meta file format")
|
||||||
}
|
}
|
||||||
|
|
||||||
// SeverityFromCVSS converts the CVSS Score (0.0 - 10.0) into a clair.Severity
|
// SeverityFromCVSS converts the CVSS Score (0.0 - 10.0) into a
|
||||||
// following the qualitative rating scale available in the CVSS v3.0
|
// database.Severity following the qualitative rating scale available in the
|
||||||
// specification (https://www.first.org/cvss/specification-document), Table 14.
|
// CVSS v3.0 specification (https://www.first.org/cvss/specification-document),
|
||||||
|
// Table 14.
|
||||||
|
//
|
||||||
// The Negligible level is set for CVSS scores between [0, 1), replacing the
|
// The Negligible level is set for CVSS scores between [0, 1), replacing the
|
||||||
// specified None level, originally used for a score of 0.
|
// specified None level, originally used for a score of 0.
|
||||||
func SeverityFromCVSS(score float64) clair.Severity {
|
func SeverityFromCVSS(score float64) database.Severity {
|
||||||
switch {
|
switch {
|
||||||
case score < 1.0:
|
case score < 1.0:
|
||||||
return clair.Negligible
|
return database.NegligibleSeverity
|
||||||
case score < 3.9:
|
case score < 3.9:
|
||||||
return clair.Low
|
return database.LowSeverity
|
||||||
case score < 6.9:
|
case score < 6.9:
|
||||||
return clair.Medium
|
return database.MediumSeverity
|
||||||
case score < 8.9:
|
case score < 8.9:
|
||||||
return clair.High
|
return database.HighSeverity
|
||||||
case score <= 10:
|
case score <= 10:
|
||||||
return clair.Critical
|
return database.CriticalSeverity
|
||||||
}
|
}
|
||||||
return clair.Unknown
|
return database.UnknownSeverity
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ import (
|
|||||||
|
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt"
|
"github.com/coreos/clair/ext/versionfmt"
|
||||||
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
||||||
@ -43,9 +42,7 @@ const (
|
|||||||
nvdURLPrefix = "https://cve.mitre.org/cgi-bin/cvename.cgi?name="
|
nvdURLPrefix = "https://cve.mitre.org/cgi-bin/cvename.cgi?name="
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var log = capnslog.NewPackageLogger("github.com/coreos/clair", "ext/vulnsrc/alpine")
|
||||||
log = capnslog.NewPackageLogger("github.com/coreos/clair", "ext/vulnsrc/alpine")
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
vulnsrc.RegisterUpdater("alpine", &updater{})
|
vulnsrc.RegisterUpdater("alpine", &updater{})
|
||||||
@ -230,7 +227,7 @@ func parse33YAML(r io.Reader) (vulns []database.Vulnerability, err error) {
|
|||||||
|
|
||||||
vulns = append(vulns, database.Vulnerability{
|
vulns = append(vulns, database.Vulnerability{
|
||||||
Name: fix,
|
Name: fix,
|
||||||
Severity: clair.Unknown,
|
Severity: database.UnknownSeverity,
|
||||||
Link: nvdURLPrefix + fix,
|
Link: nvdURLPrefix + fix,
|
||||||
FixedIn: []database.FeatureVersion{
|
FixedIn: []database.FeatureVersion{
|
||||||
{
|
{
|
||||||
@ -284,7 +281,7 @@ func parse34YAML(r io.Reader) (vulns []database.Vulnerability, err error) {
|
|||||||
|
|
||||||
for _, vulnStr := range vulnStrs {
|
for _, vulnStr := range vulnStrs {
|
||||||
var vuln database.Vulnerability
|
var vuln database.Vulnerability
|
||||||
vuln.Severity = clair.Unknown
|
vuln.Severity = database.UnknownSeverity
|
||||||
vuln.Name = vulnStr
|
vuln.Name = vulnStr
|
||||||
vuln.Link = nvdURLPrefix + vulnStr
|
vuln.Link = nvdURLPrefix + vulnStr
|
||||||
vuln.FixedIn = []database.FeatureVersion{
|
vuln.FixedIn = []database.FeatureVersion{
|
||||||
|
@ -27,7 +27,6 @@ import (
|
|||||||
|
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt"
|
"github.com/coreos/clair/ext/versionfmt"
|
||||||
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
||||||
@ -158,7 +157,7 @@ func parseDebianJSON(data *jsonData) (vulnerabilities []database.Vulnerability,
|
|||||||
vulnerability = &database.Vulnerability{
|
vulnerability = &database.Vulnerability{
|
||||||
Name: vulnName,
|
Name: vulnName,
|
||||||
Link: strings.Join([]string{cveURLPrefix, "/", vulnName}, ""),
|
Link: strings.Join([]string{cveURLPrefix, "/", vulnName}, ""),
|
||||||
Severity: clair.Unknown,
|
Severity: database.UnknownSeverity,
|
||||||
Description: vulnNode.Description,
|
Description: vulnNode.Description,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,40 +219,40 @@ func parseDebianJSON(data *jsonData) (vulnerabilities []database.Vulnerability,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SeverityFromUrgency converts the urgency scale used by the Debian Security
|
// SeverityFromUrgency converts the urgency scale used by the Debian Security
|
||||||
// Bug Tracker into a clair.Severity.
|
// Bug Tracker into a database.Severity.
|
||||||
func SeverityFromUrgency(urgency string) clair.Severity {
|
func SeverityFromUrgency(urgency string) database.Severity {
|
||||||
switch urgency {
|
switch urgency {
|
||||||
case "not yet assigned":
|
case "not yet assigned":
|
||||||
return clair.Unknown
|
return database.UnknownSeverity
|
||||||
|
|
||||||
case "end-of-life":
|
case "end-of-life":
|
||||||
fallthrough
|
fallthrough
|
||||||
case "unimportant":
|
case "unimportant":
|
||||||
return clair.Negligible
|
return database.NegligibleSeverity
|
||||||
|
|
||||||
case "low":
|
case "low":
|
||||||
fallthrough
|
fallthrough
|
||||||
case "low*":
|
case "low*":
|
||||||
fallthrough
|
fallthrough
|
||||||
case "low**":
|
case "low**":
|
||||||
return clair.Low
|
return database.LowSeverity
|
||||||
|
|
||||||
case "medium":
|
case "medium":
|
||||||
fallthrough
|
fallthrough
|
||||||
case "medium*":
|
case "medium*":
|
||||||
fallthrough
|
fallthrough
|
||||||
case "medium**":
|
case "medium**":
|
||||||
return clair.Medium
|
return database.MediumSeverity
|
||||||
|
|
||||||
case "high":
|
case "high":
|
||||||
fallthrough
|
fallthrough
|
||||||
case "high*":
|
case "high*":
|
||||||
fallthrough
|
fallthrough
|
||||||
case "high**":
|
case "high**":
|
||||||
return clair.High
|
return database.HighSeverity
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log.Warningf("could not determine vulnerability severity from: %s", urgency)
|
log.Warningf("could not determine vulnerability severity from: %s", urgency)
|
||||||
return clair.Unknown
|
return database.UnknownSeverity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt"
|
"github.com/coreos/clair/ext/versionfmt"
|
||||||
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
||||||
@ -37,7 +36,7 @@ func TestDebianParser(t *testing.T) {
|
|||||||
for _, vulnerability := range response.Vulnerabilities {
|
for _, vulnerability := range response.Vulnerabilities {
|
||||||
if vulnerability.Name == "CVE-2015-1323" {
|
if vulnerability.Name == "CVE-2015-1323" {
|
||||||
assert.Equal(t, "https://security-tracker.debian.org/tracker/CVE-2015-1323", vulnerability.Link)
|
assert.Equal(t, "https://security-tracker.debian.org/tracker/CVE-2015-1323", vulnerability.Link)
|
||||||
assert.Equal(t, clair.Low, vulnerability.Severity)
|
assert.Equal(t, database.LowSeverity, vulnerability.Severity)
|
||||||
assert.Equal(t, "This vulnerability is not very dangerous.", vulnerability.Description)
|
assert.Equal(t, "This vulnerability is not very dangerous.", vulnerability.Description)
|
||||||
|
|
||||||
expectedFeatureVersions := []database.FeatureVersion{
|
expectedFeatureVersions := []database.FeatureVersion{
|
||||||
@ -68,7 +67,7 @@ func TestDebianParser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
} else if vulnerability.Name == "CVE-2003-0779" {
|
} else if vulnerability.Name == "CVE-2003-0779" {
|
||||||
assert.Equal(t, "https://security-tracker.debian.org/tracker/CVE-2003-0779", vulnerability.Link)
|
assert.Equal(t, "https://security-tracker.debian.org/tracker/CVE-2003-0779", vulnerability.Link)
|
||||||
assert.Equal(t, clair.High, vulnerability.Severity)
|
assert.Equal(t, database.HighSeverity, vulnerability.Severity)
|
||||||
assert.Equal(t, "But this one is very dangerous.", vulnerability.Description)
|
assert.Equal(t, "But this one is very dangerous.", vulnerability.Description)
|
||||||
|
|
||||||
expectedFeatureVersions := []database.FeatureVersion{
|
expectedFeatureVersions := []database.FeatureVersion{
|
||||||
@ -109,7 +108,7 @@ func TestDebianParser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
} else if vulnerability.Name == "CVE-2013-2685" {
|
} else if vulnerability.Name == "CVE-2013-2685" {
|
||||||
assert.Equal(t, "https://security-tracker.debian.org/tracker/CVE-2013-2685", vulnerability.Link)
|
assert.Equal(t, "https://security-tracker.debian.org/tracker/CVE-2013-2685", vulnerability.Link)
|
||||||
assert.Equal(t, clair.Negligible, vulnerability.Severity)
|
assert.Equal(t, database.NegligibleSeverity, vulnerability.Severity)
|
||||||
assert.Equal(t, "Un-affected packages.", vulnerability.Description)
|
assert.Equal(t, "Un-affected packages.", vulnerability.Description)
|
||||||
|
|
||||||
expectedFeatureVersions := []database.FeatureVersion{
|
expectedFeatureVersions := []database.FeatureVersion{
|
||||||
|
@ -27,7 +27,6 @@ import (
|
|||||||
|
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt"
|
"github.com/coreos/clair/ext/versionfmt"
|
||||||
"github.com/coreos/clair/ext/versionfmt/rpm"
|
"github.com/coreos/clair/ext/versionfmt/rpm"
|
||||||
@ -337,20 +336,20 @@ func link(def definition) (link string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func severity(def definition) clair.Severity {
|
func severity(def definition) database.Severity {
|
||||||
switch strings.ToLower(def.Severity) {
|
switch strings.ToLower(def.Severity) {
|
||||||
case "n/a":
|
case "n/a":
|
||||||
return clair.Negligible
|
return database.NegligibleSeverity
|
||||||
case "low":
|
case "low":
|
||||||
return clair.Low
|
return database.LowSeverity
|
||||||
case "moderate":
|
case "moderate":
|
||||||
return clair.Medium
|
return database.MediumSeverity
|
||||||
case "important":
|
case "important":
|
||||||
return clair.High
|
return database.HighSeverity
|
||||||
case "critical":
|
case "critical":
|
||||||
return clair.Critical
|
return database.CriticalSeverity
|
||||||
default:
|
default:
|
||||||
log.Warningf("could not determine vulnerability severity from: %s.", def.Severity)
|
log.Warningf("could not determine vulnerability severity from: %s.", def.Severity)
|
||||||
return clair.Unknown
|
return database.UnknownSeverity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt/rpm"
|
"github.com/coreos/clair/ext/versionfmt/rpm"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -38,7 +37,7 @@ func TestOracleParser(t *testing.T) {
|
|||||||
if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) {
|
if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) {
|
||||||
assert.Equal(t, "ELSA-2015-1193", vulnerabilities[0].Name)
|
assert.Equal(t, "ELSA-2015-1193", vulnerabilities[0].Name)
|
||||||
assert.Equal(t, "http://linux.oracle.com/errata/ELSA-2015-1193.html", vulnerabilities[0].Link)
|
assert.Equal(t, "http://linux.oracle.com/errata/ELSA-2015-1193.html", vulnerabilities[0].Link)
|
||||||
assert.Equal(t, clair.Medium, vulnerabilities[0].Severity)
|
assert.Equal(t, database.MediumSeverity, vulnerabilities[0].Severity)
|
||||||
assert.Equal(t, ` [3.1.1-7] Resolves: rhbz#1217104 CVE-2015-0252 `, vulnerabilities[0].Description)
|
assert.Equal(t, ` [3.1.1-7] Resolves: rhbz#1217104 CVE-2015-0252 `, vulnerabilities[0].Description)
|
||||||
|
|
||||||
expectedFeatureVersions := []database.FeatureVersion{
|
expectedFeatureVersions := []database.FeatureVersion{
|
||||||
@ -86,7 +85,7 @@ func TestOracleParser(t *testing.T) {
|
|||||||
if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) {
|
if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) {
|
||||||
assert.Equal(t, "ELSA-2015-1207", vulnerabilities[0].Name)
|
assert.Equal(t, "ELSA-2015-1207", vulnerabilities[0].Name)
|
||||||
assert.Equal(t, "http://linux.oracle.com/errata/ELSA-2015-1207.html", vulnerabilities[0].Link)
|
assert.Equal(t, "http://linux.oracle.com/errata/ELSA-2015-1207.html", vulnerabilities[0].Link)
|
||||||
assert.Equal(t, clair.Critical, vulnerabilities[0].Severity)
|
assert.Equal(t, database.CriticalSeverity, vulnerabilities[0].Severity)
|
||||||
assert.Equal(t, ` [38.1.0-1.0.1.el7_1] - Add firefox-oracle-default-prefs.js and remove the corresponding Red Hat file [38.1.0-1] - Update to 38.1.0 ESR [38.0.1-2] - Fixed rhbz#1222807 by removing preun section `, vulnerabilities[0].Description)
|
assert.Equal(t, ` [38.1.0-1.0.1.el7_1] - Add firefox-oracle-default-prefs.js and remove the corresponding Red Hat file [38.1.0-1] - Update to 38.1.0 ESR [38.0.1-2] - Fixed rhbz#1222807 by removing preun section `, vulnerabilities[0].Description)
|
||||||
expectedFeatureVersions := []database.FeatureVersion{
|
expectedFeatureVersions := []database.FeatureVersion{
|
||||||
{
|
{
|
||||||
|
@ -27,7 +27,6 @@ import (
|
|||||||
|
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt"
|
"github.com/coreos/clair/ext/versionfmt"
|
||||||
"github.com/coreos/clair/ext/versionfmt/rpm"
|
"github.com/coreos/clair/ext/versionfmt/rpm"
|
||||||
@ -344,18 +343,18 @@ func link(def definition) (link string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func severity(def definition) clair.Severity {
|
func severity(def definition) database.Severity {
|
||||||
switch strings.TrimSpace(def.Title[strings.LastIndex(def.Title, "(")+1 : len(def.Title)-1]) {
|
switch strings.TrimSpace(def.Title[strings.LastIndex(def.Title, "(")+1 : len(def.Title)-1]) {
|
||||||
case "Low":
|
case "Low":
|
||||||
return clair.Low
|
return database.LowSeverity
|
||||||
case "Moderate":
|
case "Moderate":
|
||||||
return clair.Medium
|
return database.MediumSeverity
|
||||||
case "Important":
|
case "Important":
|
||||||
return clair.High
|
return database.HighSeverity
|
||||||
case "Critical":
|
case "Critical":
|
||||||
return clair.Critical
|
return database.CriticalSeverity
|
||||||
default:
|
default:
|
||||||
log.Warning("could not determine vulnerability severity from: %s.", def.Title)
|
log.Warning("could not determine vulnerability severity from: %s.", def.Title)
|
||||||
return clair.Unknown
|
return database.UnknownSeverity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt/rpm"
|
"github.com/coreos/clair/ext/versionfmt/rpm"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -36,7 +35,7 @@ func TestRHELParser(t *testing.T) {
|
|||||||
if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) {
|
if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) {
|
||||||
assert.Equal(t, "RHSA-2015:1193", vulnerabilities[0].Name)
|
assert.Equal(t, "RHSA-2015:1193", vulnerabilities[0].Name)
|
||||||
assert.Equal(t, "https://rhn.redhat.com/errata/RHSA-2015-1193.html", vulnerabilities[0].Link)
|
assert.Equal(t, "https://rhn.redhat.com/errata/RHSA-2015-1193.html", vulnerabilities[0].Link)
|
||||||
assert.Equal(t, clair.Medium, vulnerabilities[0].Severity)
|
assert.Equal(t, database.MediumSeverity, vulnerabilities[0].Severity)
|
||||||
assert.Equal(t, `Xerces-C is a validating XML parser written in a portable subset of C++. A flaw was found in the way the Xerces-C XML parser processed certain XML documents. A remote attacker could provide specially crafted XML input that, when parsed by an application using Xerces-C, would cause that application to crash.`, vulnerabilities[0].Description)
|
assert.Equal(t, `Xerces-C is a validating XML parser written in a portable subset of C++. A flaw was found in the way the Xerces-C XML parser processed certain XML documents. A remote attacker could provide specially crafted XML input that, when parsed by an application using Xerces-C, would cause that application to crash.`, vulnerabilities[0].Description)
|
||||||
|
|
||||||
expectedFeatureVersions := []database.FeatureVersion{
|
expectedFeatureVersions := []database.FeatureVersion{
|
||||||
@ -83,7 +82,7 @@ func TestRHELParser(t *testing.T) {
|
|||||||
if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) {
|
if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) {
|
||||||
assert.Equal(t, "RHSA-2015:1207", vulnerabilities[0].Name)
|
assert.Equal(t, "RHSA-2015:1207", vulnerabilities[0].Name)
|
||||||
assert.Equal(t, "https://rhn.redhat.com/errata/RHSA-2015-1207.html", vulnerabilities[0].Link)
|
assert.Equal(t, "https://rhn.redhat.com/errata/RHSA-2015-1207.html", vulnerabilities[0].Link)
|
||||||
assert.Equal(t, clair.Critical, vulnerabilities[0].Severity)
|
assert.Equal(t, database.CriticalSeverity, vulnerabilities[0].Severity)
|
||||||
assert.Equal(t, `Mozilla Firefox is an open source web browser. XULRunner provides the XUL Runtime environment for Mozilla Firefox. Several flaws were found in the processing of malformed web content. A web page containing malicious content could cause Firefox to crash or, potentially, execute arbitrary code with the privileges of the user running Firefox.`, vulnerabilities[0].Description)
|
assert.Equal(t, `Mozilla Firefox is an open source web browser. XULRunner provides the XUL Runtime environment for Mozilla Firefox. Several flaws were found in the processing of malformed web content. A web page containing malicious content could cause Firefox to crash or, potentially, execute arbitrary code with the privileges of the user running Firefox.`, vulnerabilities[0].Description)
|
||||||
|
|
||||||
expectedFeatureVersions := []database.FeatureVersion{
|
expectedFeatureVersions := []database.FeatureVersion{
|
||||||
|
@ -30,7 +30,6 @@ import (
|
|||||||
|
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt"
|
"github.com/coreos/clair/ext/versionfmt"
|
||||||
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
||||||
@ -398,30 +397,30 @@ func parseUbuntuCVE(fileContent io.Reader) (vulnerability database.Vulnerability
|
|||||||
|
|
||||||
// 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
|
||||||
if vulnerability.Severity == "" {
|
if vulnerability.Severity == "" {
|
||||||
vulnerability.Severity = clair.Unknown
|
vulnerability.Severity = database.UnknownSeverity
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SeverityFromPriority converts an priority from the Ubuntu CVE Tracker into
|
// SeverityFromPriority converts an priority from the Ubuntu CVE Tracker into
|
||||||
// a clair.Severity.
|
// a database.Severity.
|
||||||
func SeverityFromPriority(priority string) clair.Severity {
|
func SeverityFromPriority(priority string) database.Severity {
|
||||||
switch priority {
|
switch priority {
|
||||||
case "untriaged":
|
case "untriaged":
|
||||||
return clair.Unknown
|
return database.UnknownSeverity
|
||||||
case "negligible":
|
case "negligible":
|
||||||
return clair.Negligible
|
return database.NegligibleSeverity
|
||||||
case "low":
|
case "low":
|
||||||
return clair.Low
|
return database.LowSeverity
|
||||||
case "medium":
|
case "medium":
|
||||||
return clair.Medium
|
return database.MediumSeverity
|
||||||
case "high":
|
case "high":
|
||||||
return clair.High
|
return database.HighSeverity
|
||||||
case "critical":
|
case "critical":
|
||||||
return clair.Critical
|
return database.CriticalSeverity
|
||||||
default:
|
default:
|
||||||
log.Warning("could not determine a vulnerability severity from: %s", priority)
|
log.Warning("could not determine a vulnerability severity from: %s", priority)
|
||||||
return clair.Unknown
|
return database.UnknownSeverity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/versionfmt"
|
"github.com/coreos/clair/ext/versionfmt"
|
||||||
)
|
)
|
||||||
@ -37,7 +36,7 @@ func TestUbuntuParser(t *testing.T) {
|
|||||||
vulnerability, unknownReleases, err := parseUbuntuCVE(testData)
|
vulnerability, unknownReleases, err := parseUbuntuCVE(testData)
|
||||||
if assert.Nil(t, err) {
|
if assert.Nil(t, err) {
|
||||||
assert.Equal(t, "CVE-2015-4471", vulnerability.Name)
|
assert.Equal(t, "CVE-2015-4471", vulnerability.Name)
|
||||||
assert.Equal(t, clair.Medium, vulnerability.Severity)
|
assert.Equal(t, database.MediumSeverity, vulnerability.Severity)
|
||||||
assert.Equal(t, "Off-by-one error in the lzxd_decompress function in lzxd.c in libmspack before 0.5 allows remote attackers to cause a denial of service (buffer under-read and application crash) via a crafted CAB archive.", vulnerability.Description)
|
assert.Equal(t, "Off-by-one error in the lzxd_decompress function in lzxd.c in libmspack before 0.5 allows remote attackers to cause a denial of service (buffer under-read and application crash) via a crafted CAB archive.", vulnerability.Description)
|
||||||
|
|
||||||
// Unknown release (line 28)
|
// Unknown release (line 28)
|
||||||
|
139
severity.go
139
severity.go
@ -1,139 +0,0 @@
|
|||||||
// Copyright 2017 clair authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package clair
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql/driver"
|
|
||||||
"errors"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrFailedToParseSeverity is the error returned when a severity could not
|
|
||||||
// be parsed from a string.
|
|
||||||
ErrFailedToParseSeverity = errors.New("failed to parse Severity from input")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Severity defines a standard scale for measuring the severity of a
|
|
||||||
// vulnerability.
|
|
||||||
type Severity string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Unknown is either a security problem that has not been
|
|
||||||
// assigned to a priority yet or a priority that our system
|
|
||||||
// did not recognize.
|
|
||||||
Unknown Severity = "Unknown"
|
|
||||||
|
|
||||||
// Negligible is technically a security problem, but is
|
|
||||||
// only theoretical in nature, requires a very special
|
|
||||||
// situation, has almost no install base, or does no real
|
|
||||||
// damage. These tend not to get backport from upstreams,
|
|
||||||
// and will likely not be included in security updates unless
|
|
||||||
// there is an easy fix and some other issue causes an update.
|
|
||||||
Negligible Severity = "Negligible"
|
|
||||||
|
|
||||||
// Low is a security problem, but is hard to
|
|
||||||
// exploit due to environment, requires a user-assisted
|
|
||||||
// attack, a small install base, or does very little damage.
|
|
||||||
// These tend to be included in security updates only when
|
|
||||||
// higher priority issues require an update, or if many
|
|
||||||
// low priority issues have built up.
|
|
||||||
Low Severity = "Low"
|
|
||||||
|
|
||||||
// Medium is a real security problem, and is exploitable
|
|
||||||
// for many people. Includes network daemon denial of service
|
|
||||||
// attacks, cross-site scripting, and gaining user privileges.
|
|
||||||
// Updates should be made soon for this priority of issue.
|
|
||||||
Medium Severity = "Medium"
|
|
||||||
|
|
||||||
// High is a real problem, exploitable for many people in a default
|
|
||||||
// installation. Includes serious remote denial of services,
|
|
||||||
// local root privilege escalations, or data loss.
|
|
||||||
High Severity = "High"
|
|
||||||
|
|
||||||
// Critical is a world-burning problem, exploitable for nearly all people
|
|
||||||
// in a default installation of Linux. Includes remote root
|
|
||||||
// privilege escalations, or massive data loss.
|
|
||||||
Critical Severity = "Critical"
|
|
||||||
|
|
||||||
// Defcon1 is a Critical problem which has been manually highlighted by
|
|
||||||
// the team. It requires an immediate attention.
|
|
||||||
Defcon1 Severity = "Defcon1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Severities lists all known severities, ordered from lowest to highest.
|
|
||||||
var Severities = []Severity{
|
|
||||||
Unknown,
|
|
||||||
Negligible,
|
|
||||||
Low,
|
|
||||||
Medium,
|
|
||||||
High,
|
|
||||||
Critical,
|
|
||||||
Defcon1,
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSeverity attempts to parse a string into a standard Severity value.
|
|
||||||
func NewSeverity(s string) (Severity, error) {
|
|
||||||
for _, ss := range Severities {
|
|
||||||
if strings.EqualFold(s, string(ss)) {
|
|
||||||
return ss, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Unknown, ErrFailedToParseSeverity
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare determines the equality of two severities.
|
|
||||||
//
|
|
||||||
// If the severities are equal, returns 0.
|
|
||||||
// If the receiever is less, returns -1.
|
|
||||||
// If the receiver is greater, returns 1.
|
|
||||||
func (s Severity) Compare(s2 Severity) int {
|
|
||||||
var i1, i2 int
|
|
||||||
|
|
||||||
for i1 = 0; i1 < len(Severities); i1 = i1 + 1 {
|
|
||||||
if s == Severities[i1] {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i2 = 0; i2 < len(Severities); i2 = i2 + 1 {
|
|
||||||
if s2 == Severities[i2] {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return i1 - i2
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan implements the database/sql.Scanner interface.
|
|
||||||
func (s *Severity) Scan(value interface{}) error {
|
|
||||||
val, ok := value.([]byte)
|
|
||||||
if !ok {
|
|
||||||
return errors.New("could not scan a Severity from a non-string input")
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
*s, err = NewSeverity(string(val))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value implements the database/sql/driver.Valuer interface.
|
|
||||||
func (s Severity) Value() (driver.Value, error) {
|
|
||||||
return string(s), nil
|
|
||||||
}
|
|
@ -12,10 +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.
|
||||||
|
|
||||||
// Package updater updates the vulnerability database periodically using the
|
package clair
|
||||||
// registered vulnerability source updaters and vulnerability metadata
|
|
||||||
// appenders.
|
|
||||||
package updater
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@ -27,7 +24,6 @@ import (
|
|||||||
"github.com/pborman/uuid"
|
"github.com/pborman/uuid"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
"github.com/coreos/clair"
|
|
||||||
"github.com/coreos/clair/config"
|
"github.com/coreos/clair/config"
|
||||||
"github.com/coreos/clair/database"
|
"github.com/coreos/clair/database"
|
||||||
"github.com/coreos/clair/ext/vulnmdsrc"
|
"github.com/coreos/clair/ext/vulnmdsrc"
|
||||||
@ -36,16 +32,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
flagName = "updater/last"
|
updaterLastFlagName = "updater/last"
|
||||||
notesFlagName = "updater/notes"
|
updaterLockName = "updater"
|
||||||
|
updaterLockDuration = updaterLockRefreshDuration + time.Minute*2
|
||||||
lockName = "updater"
|
updaterLockRefreshDuration = time.Minute * 8
|
||||||
lockDuration = refreshLockDuration + time.Minute*2
|
|
||||||
refreshLockDuration = time.Minute * 8
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
log = capnslog.NewPackageLogger("github.com/coreos/clair", "updater")
|
log = capnslog.NewPackageLogger("github.com/coreos/clair", "clair")
|
||||||
|
|
||||||
promUpdaterErrorsTotal = prometheus.NewCounter(prometheus.CounterOpts{
|
promUpdaterErrorsTotal = prometheus.NewCounter(prometheus.CounterOpts{
|
||||||
Name: "clair_updater_errors_total",
|
Name: "clair_updater_errors_total",
|
||||||
@ -69,8 +63,9 @@ func init() {
|
|||||||
prometheus.MustRegister(promUpdaterNotesTotal)
|
prometheus.MustRegister(promUpdaterNotesTotal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run updates the vulnerability database at regular intervals.
|
// RunUpdater begins a process that updates the vulnerability database at
|
||||||
func Run(config *config.UpdaterConfig, datastore database.Datastore, st *stopper.Stopper) {
|
// regular intervals.
|
||||||
|
func RunUpdater(config *config.UpdaterConfig, 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.
|
||||||
@ -100,12 +95,12 @@ func Run(config *config.UpdaterConfig, datastore database.Datastore, st *stopper
|
|||||||
if nextUpdate.Before(time.Now().UTC()) {
|
if nextUpdate.Before(time.Now().UTC()) {
|
||||||
// Attempt to get a lock on the the update.
|
// Attempt to get a lock on the the update.
|
||||||
log.Debug("attempting to obtain update lock")
|
log.Debug("attempting to obtain update lock")
|
||||||
hasLock, hasLockUntil := datastore.Lock(lockName, whoAmI, lockDuration, false)
|
hasLock, hasLockUntil := datastore.Lock(updaterLockName, whoAmI, updaterLockDuration, false)
|
||||||
if hasLock {
|
if hasLock {
|
||||||
// Launch update in a new go routine.
|
// Launch update in a new go routine.
|
||||||
doneC := make(chan bool, 1)
|
doneC := make(chan bool, 1)
|
||||||
go func() {
|
go func() {
|
||||||
Update(datastore, firstUpdate)
|
update(datastore, firstUpdate)
|
||||||
doneC <- true
|
doneC <- true
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -113,23 +108,23 @@ func Run(config *config.UpdaterConfig, datastore database.Datastore, st *stopper
|
|||||||
select {
|
select {
|
||||||
case <-doneC:
|
case <-doneC:
|
||||||
done = true
|
done = true
|
||||||
case <-time.After(refreshLockDuration):
|
case <-time.After(updaterLockRefreshDuration):
|
||||||
// Refresh the lock until the update is done.
|
// Refresh the lock until the update is done.
|
||||||
datastore.Lock(lockName, whoAmI, lockDuration, true)
|
datastore.Lock(updaterLockName, whoAmI, updaterLockDuration, true)
|
||||||
case <-st.Chan():
|
case <-st.Chan():
|
||||||
stop = true
|
stop = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock the update.
|
// Unlock the update.
|
||||||
datastore.Unlock(lockName, whoAmI)
|
datastore.Unlock(updaterLockName, whoAmI)
|
||||||
|
|
||||||
if stop {
|
if stop {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
lockOwner, lockExpiration, err := datastore.FindLock(lockName)
|
lockOwner, lockExpiration, err := datastore.FindLock(updaterLockName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("update lock is already taken")
|
log.Debug("update lock is already taken")
|
||||||
nextUpdate = hasLockUntil
|
nextUpdate = hasLockUntil
|
||||||
@ -162,9 +157,9 @@ func Run(config *config.UpdaterConfig, datastore database.Datastore, st *stopper
|
|||||||
log.Info("updater service stopped")
|
log.Info("updater service stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
defer setUpdaterDuration(time.Now())
|
defer setUpdaterDuration(time.Now())
|
||||||
|
|
||||||
log.Info("updating vulnerabilities")
|
log.Info("updating vulnerabilities")
|
||||||
@ -195,7 +190,7 @@ func Update(datastore database.Datastore, firstUpdate bool) {
|
|||||||
|
|
||||||
// Update last successful update if every fetchers worked properly.
|
// Update last successful update if every fetchers worked properly.
|
||||||
if status {
|
if status {
|
||||||
datastore.InsertKeyValue(flagName, strconv.FormatInt(time.Now().UTC().Unix(), 10))
|
datastore.InsertKeyValue(updaterLastFlagName, strconv.FormatInt(time.Now().UTC().Unix(), 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("update finished")
|
log.Info("update finished")
|
||||||
@ -293,7 +288,7 @@ func addMetadata(datastore database.Datastore, vulnerabilities []database.Vulner
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getLastUpdate(datastore database.Datastore) (time.Time, bool, error) {
|
func getLastUpdate(datastore database.Datastore) (time.Time, bool, error) {
|
||||||
lastUpdateTSS, err := datastore.GetKeyValue(flagName)
|
lastUpdateTSS, err := datastore.GetKeyValue(updaterLastFlagName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Time{}, false, err
|
return time.Time{}, false, err
|
||||||
}
|
}
|
||||||
@ -316,7 +311,7 @@ type lockableVulnerability struct {
|
|||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lv *lockableVulnerability) appendFunc(metadataKey string, metadata interface{}, severity clair.Severity) {
|
func (lv *lockableVulnerability) appendFunc(metadataKey string, metadata interface{}, severity database.Severity) {
|
||||||
lv.Lock()
|
lv.Lock()
|
||||||
defer lv.Unlock()
|
defer lv.Unlock()
|
||||||
|
|
||||||
@ -329,7 +324,7 @@ func (lv *lockableVulnerability) appendFunc(metadataKey string, metadata interfa
|
|||||||
lv.Metadata[metadataKey] = metadata
|
lv.Metadata[metadataKey] = metadata
|
||||||
|
|
||||||
// If necessary, provide a severity for the vulnerability.
|
// If necessary, provide a severity for the vulnerability.
|
||||||
if lv.Severity == clair.Unknown {
|
if lv.Severity == database.UnknownSeverity {
|
||||||
lv.Severity = severity
|
lv.Severity = severity
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 clair authors
|
// Copyright 2017 clair authors
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -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.
|
||||||
|
|
||||||
package updater
|
package clair
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
Loading…
Reference in New Issue
Block a user