Skip to content

Commit

Permalink
database: Restructure database folder
Browse files Browse the repository at this point in the history
- one pgsql data model per folder, and one table per file
- one data model per file
  • Loading branch information
KeyboardNerd committed Mar 1, 2019
1 parent 4fa03d1 commit d3a1e55
Show file tree
Hide file tree
Showing 43 changed files with 1,336 additions and 1,290 deletions.
82 changes: 82 additions & 0 deletions database/ancestry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package database

// Ancestry is a manifest that keeps all layers in an image in order.
type Ancestry struct {
// Name is a globally unique value for a set of layers. This is often the
// sha256 digest of an OCI/Docker manifest.
Name string `json:"name"`
// By contains the processors that are used when computing the
// content of this ancestry.
By []Detector `json:"by"`
// Layers should be ordered and i_th layer is the parent of i+1_th layer in
// the slice.
Layers []AncestryLayer `json:"layers"`
}

// Valid checks if the ancestry is compliant to spec.
func (a *Ancestry) Valid() bool {
if a == nil {
return false
}

if a.Name == "" {
return false
}

for _, d := range a.By {
if !d.Valid() {
return false
}
}

for _, l := range a.Layers {
if !l.Valid() {
return false
}
}

return true
}

// AncestryLayer is a layer with all detected namespaced features.
type AncestryLayer struct {
// Hash is the sha-256 tarsum on the layer's blob content.
Hash string `json:"hash"`
// Features are the features introduced by this layer when it was
// processed.
Features []AncestryFeature `json:"features"`
}

// Valid checks if the Ancestry Layer is compliant to the spec.
func (l *AncestryLayer) Valid() bool {
if l == nil {
return false
}

if l.Hash == "" {
return false
}

return true
}

// GetFeatures returns the Ancestry's features.
func (l *AncestryLayer) GetFeatures() []NamespacedFeature {
nsf := make([]NamespacedFeature, 0, len(l.Features))
for _, f := range l.Features {
nsf = append(nsf, f.NamespacedFeature)
}

return nsf
}

// AncestryFeature is a namespaced feature with the detectors used to
// find this feature.
type AncestryFeature struct {
NamespacedFeature `json:"namespacedFeature"`

// FeatureBy is the detector that detected the feature.
FeatureBy Detector `json:"featureBy"`
// NamespaceBy is the detector that detected the namespace.
NamespaceBy Detector `json:"namespaceBy"`
}
82 changes: 82 additions & 0 deletions database/feature.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package database

// Feature represents a package detected in a layer but the namespace is not
// determined.
//
// e.g. Name: Libssl1.0, Version: 1.0, VersionFormat: dpkg, Type: binary
// dpkg is the version format of the installer package manager, which in this
// case could be dpkg or apk.
type Feature struct {
Name string `json:"name"`
Version string `json:"version"`
VersionFormat string `json:"versionFormat"`
Type FeatureType `json:"type"`
}

// 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 `json:"feature"`

Namespace Namespace `json:"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 {
// FeatureType determines which type of package it affects.
FeatureType FeatureType
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
}

// NullableAffectedNamespacedFeature is an affectednamespacedfeature with
// whether it's found in datastore.
type NullableAffectedNamespacedFeature struct {
AffectedNamespacedFeature

Valid bool
}

func NewFeature(name string, version string, versionFormat string, featureType FeatureType) *Feature {
return &Feature{name, version, versionFormat, featureType}
}

func NewBinaryPackage(name string, version string, versionFormat string) *Feature {
return &Feature{name, version, versionFormat, BinaryPackage}
}

func NewSourcePackage(name string, version string, versionFormat string) *Feature {
return &Feature{name, version, versionFormat, SourcePackage}
}

func NewNamespacedFeature(namespace *Namespace, feature *Feature) *NamespacedFeature {
// TODO: namespaced feature should use pointer values
return &NamespacedFeature{*feature, *namespace}
}
45 changes: 45 additions & 0 deletions database/layer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package database

// Layer is a layer with all the detected features and namespaces.
type Layer struct {
// Hash is the sha-256 tarsum on the layer's blob content.
Hash string `json:"hash"`
// By contains a list of detectors scanned this Layer.
By []Detector `json:"by"`
Namespaces []LayerNamespace `json:"namespaces"`
Features []LayerFeature `json:"features"`
}

func (l *Layer) GetFeatures() []Feature {
features := make([]Feature, 0, len(l.Features))
for _, f := range l.Features {
features = append(features, f.Feature)
}

return features
}

func (l *Layer) GetNamespaces() []Namespace {
namespaces := make([]Namespace, 0, len(l.Namespaces))
for _, ns := range l.Namespaces {
namespaces = append(namespaces, ns.Namespace)
}

return namespaces
}

// LayerNamespace is a namespace with detection information.
type LayerNamespace struct {
Namespace `json:"namespace"`

// By is the detector found the namespace.
By Detector `json:"by"`
}

// LayerFeature is a feature with detection information.
type LayerFeature struct {
Feature `json:"feature"`

// By is the detector found the feature.
By Detector `json:"by"`
}
27 changes: 27 additions & 0 deletions database/metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package database

import (
"database/sql/driver"
"encoding/json"
)

// MetadataMap is for storing the metadata returned by vulnerability database.
type MetadataMap map[string]interface{}

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
}
Loading

0 comments on commit d3a1e55

Please sign in to comment.