// 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" "encoding/json" "time" "github.com/coreos/clair/pkg/pagination" ) // Processors are extentions to scan a layer's content. type Processors struct { Listers []string Detectors []string } // Ancestry is a manifest that keeps all layers in an image in order. type Ancestry struct { Name string // ProcessedBy contains the processors that are used when computing the // content of this ancestry. ProcessedBy Processors // Layers should be ordered and i_th layer is the parent of i+1_th layer in // the slice. Layers []AncestryLayer } // AncestryLayer is a layer with all detected namespaced features. type AncestryLayer struct { Layer // DetectedFeatures are the features introduced by this layer when it was // processed. DetectedFeatures []NamespacedFeature } // Layer contains the metadata of a layer. type Layer struct { // Hash is content hash of the layer. Hash string // ProcessedBy contains the processors that processed this layer. ProcessedBy Processors } // LayerWithContent is a layer with its detected namespaces and features by // ProcessedBy. type LayerWithContent struct { Layer Namespaces []Namespace Features []Feature } // Namespace is the contextual information around features. // // e.g. Debian:7, NodeJS. type Namespace struct { Name string VersionFormat string } // Feature represents a package detected in a layer but the namespace is not // determined. // // e.g. Name: OpenSSL, Version: 1.0, VersionFormat: dpkg. // dpkg is the version format of the installer package manager, which in this // case could be dpkg or apk. type Feature struct { Name string Version string VersionFormat string } // NamespacedFeature is a feature with determined namespace and can be affected // by vulnerabilities. // // e.g. OpenSSL 1.0 dpkg Debian:7. type NamespacedFeature struct { Feature Namespace Namespace } // AffectedNamespacedFeature is a namespaced feature affected by the // vulnerabilities with fixed-in versions for this feature. type AffectedNamespacedFeature struct { NamespacedFeature AffectedBy []VulnerabilityWithFixedIn } // VulnerabilityWithFixedIn is used for AffectedNamespacedFeature to retrieve // the affecting vulnerabilities and the fixed-in versions for the feature. type VulnerabilityWithFixedIn struct { Vulnerability FixedInVersion string } // AffectedFeature is used to determine whether a namespaced feature is affected // by a Vulnerability. Namespace and Feature Name is unique. Affected Feature is // bound to vulnerability. type AffectedFeature struct { Namespace Namespace FeatureName string // FixedInVersion is known next feature version that's not affected by the // vulnerability. Empty FixedInVersion means the unaffected version is // unknown. FixedInVersion string // AffectedVersion contains the version range to determine whether or not a // feature is affected. AffectedVersion string } // VulnerabilityID is an identifier for every vulnerability. Every vulnerability // has unique namespace and name. type VulnerabilityID struct { Name string Namespace string } // Vulnerability represents CVE or similar vulnerability reports. type Vulnerability struct { Name string Namespace Namespace Description string Link string Severity Severity Metadata MetadataMap } // VulnerabilityWithAffected is an vulnerability with all known affected // features. type VulnerabilityWithAffected struct { Vulnerability Affected []AffectedFeature } // PagedVulnerableAncestries is a vulnerability with a page of affected // ancestries each with a special index attached for streaming purpose. The // current page number and next page number are for navigate. type PagedVulnerableAncestries struct { Vulnerability // Affected is a map of special indexes to Ancestries, which the pair // should be unique in a stream. Every indexes in the map should be larger // than previous page. Affected map[int]string Limit int Current pagination.Token Next pagination.Token // End signals the end of the pages. End bool } // NotificationHook is a message sent to another service to inform of a change // to a Vulnerability or the Ancestries affected by a Vulnerability. It contains // the name of a notification that should be read and marked as read via the // API. type NotificationHook struct { Name string Created time.Time Notified time.Time Deleted time.Time } // VulnerabilityNotification is a notification for vulnerability changes. type VulnerabilityNotification struct { NotificationHook Old *Vulnerability New *Vulnerability } // VulnerabilityNotificationWithVulnerable is a notification for vulnerability // changes with vulnerable ancestries. type VulnerabilityNotificationWithVulnerable struct { NotificationHook Old *PagedVulnerableAncestries New *PagedVulnerableAncestries } // MetadataMap is for storing the metadata returned by vulnerability database. type MetadataMap map[string]interface{} // NullableAffectedNamespacedFeature is an affectednamespacedfeature with // whether it's found in datastore. type NullableAffectedNamespacedFeature struct { AffectedNamespacedFeature Valid bool } // NullableVulnerability is a vulnerability with whether the vulnerability is // found in datastore. type NullableVulnerability struct { VulnerabilityWithAffected Valid bool } func (mm *MetadataMap) Scan(value interface{}) error { if value == nil { return nil } // github.com/lib/pq decodes TEXT/VARCHAR fields into strings. val, ok := value.(string) if !ok { panic("got type other than []byte from database") } return json.Unmarshal([]byte(val), mm) } func (mm *MetadataMap) Value() (driver.Value, error) { json, err := json.Marshal(*mm) return string(json), err }