Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internally version all detected content by extension #620

Merged
merged 14 commits into from
Oct 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
352 changes: 221 additions & 131 deletions api/v3/clairpb/clair.pb.go

Large diffs are not rendered by default.

48 changes: 35 additions & 13 deletions api/v3/clairpb/clair.proto
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,42 @@ message Vulnerability {
repeated Feature affected_versions = 8;
}

message Detector {
KeyboardNerd marked this conversation as resolved.
Show resolved Hide resolved
enum DType {
DETECTOR_D_TYPE_INVALID = 0;
DETECTOR_D_TYPE_NAMESPACE = 1;
DETECTOR_D_TYPE_FEATURE = 2;
}
// The name of the detector.
string name = 1;
// The version of the detector.
string version = 2;
// The type of the detector.
DType dtype = 3;
}

message Namespace {
// The name of the namespace.
string name = 1;
// The detector used to detect the namespace. This only exists when present in
// an Ancestry Feature.
Detector detector = 2;
}

message Feature {
// The name of the feature.
string name = 1;
// The name of the namespace in which the feature is detected.
string namespace_name = 2;
// The namespace in which the feature is detected.
Namespace namespace = 2;
// The specific version of this feature.
string version = 3;
// The format used to parse version numbers for the feature.
string version_format = 4;
// The detector used to detect this feature. This only exists when present in
// an Ancestry.
Detector detector = 5;
// The list of vulnerabilities that affect the feature.
repeated Vulnerability vulnerabilities = 5;
repeated Vulnerability vulnerabilities = 6;
}

message Layer {
Expand All @@ -77,12 +102,10 @@ service AncestryService {
}

message ClairStatus {
// The configured list of feature listers used to scan an ancestry.
repeated string listers = 1;
// The configured list of namespace detectors used to scan an ancestry.
repeated string detectors = 2;
// The implemented detectors in this Clair instance
repeated Detector detectors = 1;
// The time at which the updater last ran.
google.protobuf.Timestamp last_update_time = 3;
google.protobuf.Timestamp last_update_time = 2;
}

message GetAncestryRequest {
Expand All @@ -100,12 +123,11 @@ message GetAncestryResponse {
message Ancestry {
// The name of the desired ancestry.
string name = 1;
// The configured list of feature listers used to scan this ancestry.
repeated string scanned_listers = 4;
// The configured list of namespace detectors used to scan an ancestry.
repeated string scanned_detectors = 5;
// The detectors used to scan this Ancestry. It may not be the current set
// of detectors in clair status.
repeated Detector detectors = 2;
// The list of layers along with detected features in each.
repeated AncestryLayer layers = 6;
repeated AncestryLayer layers = 3;
}
// The ancestry requested.
Ancestry ancestry = 1;
Expand Down
73 changes: 51 additions & 22 deletions api/v3/clairpb/clair.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,26 +156,28 @@
}
},
"definitions": {
"DetectorDType": {
"type": "string",
"enum": [
"DETECTOR_D_TYPE_INVALID",
"DETECTOR_D_TYPE_NAMESPACE",
"DETECTOR_D_TYPE_FEATURE"
],
"default": "DETECTOR_D_TYPE_INVALID"
},
"GetAncestryResponseAncestry": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the desired ancestry."
},
"scanned_listers": {
"type": "array",
"items": {
"type": "string"
},
"description": "The configured list of feature listers used to scan this ancestry."
},
"scanned_detectors": {
"detectors": {
"type": "array",
"items": {
"type": "string"
"$ref": "#/definitions/clairDetector"
},
"description": "The configured list of namespace detectors used to scan an ancestry."
"description": "The detectors used to scan this Ancestry. It may not be the current set\nof detectors in clair status."
},
"layers": {
"type": "array",
Expand Down Expand Up @@ -268,19 +270,12 @@
"clairClairStatus": {
"type": "object",
"properties": {
"listers": {
"type": "array",
"items": {
"type": "string"
},
"description": "The configured list of feature listers used to scan an ancestry."
},
"detectors": {
"type": "array",
"items": {
"type": "string"
"$ref": "#/definitions/clairDetector"
},
"description": "The configured list of namespace detectors used to scan an ancestry."
"title": "The implemented detectors in this Clair instance"
},
"last_update_time": {
"type": "string",
Expand All @@ -289,16 +284,33 @@
}
}
},
"clairDetector": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the detector."
},
"version": {
"type": "string",
"description": "The version of the detector."
},
"dtype": {
"$ref": "#/definitions/DetectorDType",
"description": "The type of the detector."
}
}
},
"clairFeature": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the feature."
},
"namespace_name": {
"type": "string",
"description": "The name of the namespace in which the feature is detected."
"namespace": {
"$ref": "#/definitions/clairNamespace",
"description": "The namespace in which the feature is detected."
},
"version": {
"type": "string",
Expand All @@ -308,6 +320,10 @@
"type": "string",
"description": "The format used to parse version numbers for the feature."
},
"detector": {
"$ref": "#/definitions/clairDetector",
"description": "The detector used to detect this feature. This only exists when present in\nan Ancestry."
},
"vulnerabilities": {
"type": "array",
"items": {
Expand Down Expand Up @@ -360,6 +376,19 @@
"clairMarkNotificationAsReadResponse": {
"type": "object"
},
"clairNamespace": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the namespace."
},
"detector": {
"$ref": "#/definitions/clairDetector",
"description": "The detector used to detect the namespace. This only exists when present in\nan Ancestry Feature."
}
}
},
"clairPagedVulnerableAncestries": {
"type": "object",
"properties": {
Expand Down
40 changes: 31 additions & 9 deletions api/v3/clairpb/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ import (
"github.com/coreos/clair/ext/versionfmt"
)

// DatabaseDetectorTypeMapping maps the database detector type to the integer
// enum proto.
var DatabaseDetectorTypeMapping = map[database.DetectorType]Detector_DType{
database.NamespaceDetectorType: Detector_DType(1),
database.FeatureDetectorType: Detector_DType(2),
}

// PagedVulnerableAncestriesFromDatabaseModel converts database
// PagedVulnerableAncestries to api PagedVulnerableAncestries and assigns
// indexes to ancestries.
Expand Down Expand Up @@ -122,23 +129,38 @@ func VulnerabilityWithFixedInFromDatabaseModel(dbVuln database.VulnerabilityWith
return vuln, nil
}

// LayerFromDatabaseModel converts database layer to api layer.
func LayerFromDatabaseModel(dbLayer database.LayerMetadata) *Layer {
layer := Layer{Hash: dbLayer.Hash}
return &layer
}

// NamespacedFeatureFromDatabaseModel converts database namespacedFeature to api Feature.
func NamespacedFeatureFromDatabaseModel(feature database.NamespacedFeature) *Feature {
func NamespacedFeatureFromDatabaseModel(feature database.AncestryFeature) *Feature {
version := feature.Feature.Version
if version == versionfmt.MaxVersion {
version = "None"
}

return &Feature{
Name: feature.Feature.Name,
NamespaceName: feature.Namespace.Name,
Name: feature.Feature.Name,
Namespace: &Namespace{
Name: feature.Namespace.Name,
Detector: DetectorFromDatabaseModel(feature.NamespaceBy),
},
VersionFormat: feature.Namespace.VersionFormat,
Version: version,
Detector: DetectorFromDatabaseModel(feature.FeatureBy),
}
}

func DetectorFromDatabaseModel(detector database.Detector) *Detector {
return &Detector{
Name: detector.Name,
Version: detector.Version,
Dtype: DatabaseDetectorTypeMapping[detector.DType],
}
}

func DetectorsFromDatabaseModel(dbDetectors []database.Detector) []*Detector {
detectors := make([]*Detector, 0, len(dbDetectors))
for _, d := range dbDetectors {
detectors = append(detectors, DetectorFromDatabaseModel(d))
}

return detectors
}
5 changes: 2 additions & 3 deletions api/v3/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,8 @@ func (s *AncestryServer) GetAncestry(ctx context.Context, req *pb.GetAncestryReq
}

pbAncestry := &pb.GetAncestryResponse_Ancestry{
Name: ancestry.Name,
ScannedDetectors: ancestry.ProcessedBy.Detectors,
ScannedListers: ancestry.ProcessedBy.Listers,
Name: ancestry.Name,
Detectors: pb.DetectorsFromDatabaseModel(ancestry.By),
}

for _, layer := range ancestry.Layers {
Expand Down
49 changes: 28 additions & 21 deletions api/v3/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import (
// protobuf struct.
func GetClairStatus(store database.Datastore) (*pb.ClairStatus, error) {
status := &pb.ClairStatus{
Listers: clair.Processors.Listers,
Detectors: clair.Processors.Detectors,
Detectors: pb.DetectorsFromDatabaseModel(clair.EnabledDetectors),
}

t, firstUpdate, err := clair.GetLastUpdateTime(store)
Expand All @@ -34,41 +33,49 @@ func GetClairStatus(store database.Datastore) (*pb.ClairStatus, error) {

// GetPbAncestryLayer retrieves an ancestry layer with vulnerabilities and
// features in an ancestry based on the provided database layer.
func GetPbAncestryLayer(session database.Session, layer database.AncestryLayer) (*pb.GetAncestryResponse_AncestryLayer, error) {
func GetPbAncestryLayer(tx database.Session, layer database.AncestryLayer) (*pb.GetAncestryResponse_AncestryLayer, error) {
KeyboardNerd marked this conversation as resolved.
Show resolved Hide resolved
pbLayer := &pb.GetAncestryResponse_AncestryLayer{
Layer: &pb.Layer{
Hash: layer.Hash,
},
}

var (
features []database.NullableAffectedNamespacedFeature
err error
)

if features, err = session.FindAffectedNamespacedFeatures(layer.DetectedFeatures); err != nil {
features := layer.GetFeatures()
affectedFeatures, err := tx.FindAffectedNamespacedFeatures(features)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

for _, feature := range features {
// NOTE(sidac): It's quite inefficient, but the easiest way to implement
// this feature for now, we should refactor the implementation if there's
// any performance issue. It's expected that the number of features is less
// than 1000.
for _, feature := range affectedFeatures {
KeyboardNerd marked this conversation as resolved.
Show resolved Hide resolved
if !feature.Valid {
return nil, status.Error(codes.Internal, "ancestry feature is not found")
KeyboardNerd marked this conversation as resolved.
Show resolved Hide resolved
}

var (
pbFeature = pb.NamespacedFeatureFromDatabaseModel(feature.NamespacedFeature)
pbVuln *pb.Vulnerability
err error
)
for _, vuln := range feature.AffectedBy {
if pbVuln, err = pb.VulnerabilityWithFixedInFromDatabaseModel(vuln); err != nil {
return nil, status.Error(codes.Internal, err.Error())
for _, detectedFeature := range layer.Features {
if detectedFeature.NamespacedFeature != feature.NamespacedFeature {
continue
}

pbFeature.Vulnerabilities = append(pbFeature.Vulnerabilities, pbVuln)
}
var (
pbFeature = pb.NamespacedFeatureFromDatabaseModel(detectedFeature)
pbVuln *pb.Vulnerability
err error
)

for _, vuln := range feature.AffectedBy {
if pbVuln, err = pb.VulnerabilityWithFixedInFromDatabaseModel(vuln); err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

pbLayer.DetectedFeatures = append(pbLayer.DetectedFeatures, pbFeature)
pbFeature.Vulnerabilities = append(pbFeature.Vulnerabilities, pbVuln)
}

pbLayer.DetectedFeatures = append(pbLayer.DetectedFeatures, pbFeature)
}
}

return pbLayer, nil
Expand Down
7 changes: 0 additions & 7 deletions cmd/clair/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ import (
"github.com/coreos/clair"
"github.com/coreos/clair/api"
"github.com/coreos/clair/database"
"github.com/coreos/clair/ext/featurefmt"
"github.com/coreos/clair/ext/featurens"
"github.com/coreos/clair/ext/notification"
"github.com/coreos/clair/ext/vulnsrc"
"github.com/coreos/clair/pkg/pagination"
Expand All @@ -47,7 +45,6 @@ type File struct {
type Config struct {
Database database.RegistrableComponentConfig
Updater *clair.UpdaterConfig
Worker *clair.WorkerConfig
Notifier *notification.Config
API *api.Config
}
Expand All @@ -62,10 +59,6 @@ func DefaultConfig() Config {
EnabledUpdaters: vulnsrc.ListUpdaters(),
Interval: 1 * time.Hour,
},
Worker: &clair.WorkerConfig{
EnabledDetectors: featurens.ListDetectors(),
EnabledListers: featurefmt.ListListers(),
},
API: &api.Config{
HealthAddr: "0.0.0.0:6061",
Addr: "0.0.0.0:6060",
Expand Down
Loading