clair code review

This commit is contained in:
lynzabo 2017-10-09 07:48:27 -07:00
parent f8a1359a60
commit 937816dd1f
4 changed files with 173 additions and 115 deletions

View File

@ -111,11 +111,14 @@ func postLayer(w http.ResponseWriter, r *http.Request, p httprouter.Params, ctx
err = clair.ProcessLayer(ctx.Store, request.Layer.Format, request.Layer.Name, request.Layer.ParentName, request.Layer.Path, request.Layer.Headers)
if err != nil {
//tarutil: could not extract the archive
if err == tarutil.ErrCouldNotExtract ||
//tarutil: could not extract one or more files from the archive: file too big
err == tarutil.ErrExtractedFileTooBig ||
//worker: OS and/or package manager are not supported
err == clair.ErrUnsupported {
writeResponse(w, r, statusUnprocessableEntity, LayerEnvelope{Error: &Error{err.Error()}})
return postLayerRoute, statusUnprocessableEntity
return postLayerRoute, statusUnprocessableEntity //422
}
if _, badreq := err.(*commonerr.ErrBadRequest); badreq {

View File

@ -1,114 +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 main
import (
"errors"
"io/ioutil"
"os"
"time"
"gopkg.in/yaml.v2"
"github.com/coreos/clair"
"github.com/coreos/clair/api"
"github.com/coreos/clair/database"
"github.com/coreos/clair/ext/notification"
"github.com/fernet/fernet-go"
)
// ErrDatasourceNotLoaded is returned when the datasource variable in the
// configuration file is not loaded properly
var ErrDatasourceNotLoaded = errors.New("could not load configuration: no database source specified")
// File represents a YAML configuration file that namespaces all Clair
// configuration under the top-level "clair" key.
type File struct {
Clair Config `yaml:"clair"`
}
// Config is the global configuration for an instance of Clair.
type Config struct {
Database database.RegistrableComponentConfig
Updater *clair.UpdaterConfig
Notifier *notification.Config
API *api.Config
}
// DefaultConfig is a configuration that can be used as a fallback value.
func DefaultConfig() Config {
return Config{
Database: database.RegistrableComponentConfig{
Type: "pgsql",
},
Updater: &clair.UpdaterConfig{
Interval: 1 * time.Hour,
},
API: &api.Config{
Port: 6060,
HealthPort: 6061,
Timeout: 900 * time.Second,
},
Notifier: &notification.Config{
Attempts: 5,
RenotifyInterval: 2 * time.Hour,
},
}
}
// LoadConfig is a shortcut to open a file, read it, and generate a Config.
//
// It supports relative and absolute paths. Given "", it returns DefaultConfig.
func LoadConfig(path string) (config *Config, err error) {
var cfgFile File
cfgFile.Clair = DefaultConfig()
if path == "" {
return &cfgFile.Clair, nil
}
f, err := os.Open(os.ExpandEnv(path))
if err != nil {
return
}
defer f.Close()
d, err := ioutil.ReadAll(f)
if err != nil {
return
}
err = yaml.Unmarshal(d, &cfgFile)
if err != nil {
return
}
config = &cfgFile.Clair
// Generate a pagination key if none is provided.
if config.API.PaginationKey == "" {
var key fernet.Key
if err = key.Generate(); err != nil {
return
}
config.API.PaginationKey = key.Encode()
} else {
_, err = fernet.DecodeKey(config.API.PaginationKey)
if err != nil {
err = errors.New("Invalid Pagination key; must be 32-bit URL-safe base64")
return
}
}
return
}

View File

@ -55,8 +55,97 @@ import (
_ "github.com/coreos/clair/ext/vulnsrc/oracle"
_ "github.com/coreos/clair/ext/vulnsrc/rhel"
_ "github.com/coreos/clair/ext/vulnsrc/ubuntu"
"gopkg.in/yaml.v2"
"github.com/coreos/clair/ext/notification"
"io/ioutil"
"github.com/fernet/fernet-go"
"errors"
)
// ErrDatasourceNotLoaded is returned when the datasource variable in the
// configuration file is not loaded properly
var ErrDatasourceNotLoaded = errors.New("could not load configuration: no database source specified")
// File represents a YAML configuration file that namespaces all Clair
// configuration under the top-level "clair" key.
type File struct {
Clair Config `yaml:"clair"`
}
// Config is the global configuration for an instance of Clair.
type Config struct {
Database database.RegistrableComponentConfig
Updater *clair.UpdaterConfig
Notifier *notification.Config
API *api.Config
}
// DefaultConfig is a configuration that can be used as a fallback value.
func DefaultConfig() Config {
return Config{
Database: database.RegistrableComponentConfig{
Type: "pgsql",
},
Updater: &clair.UpdaterConfig{
Interval: 1 * time.Hour,
},
API: &api.Config{
Port: 6060,
HealthPort: 6061,
Timeout: 900 * time.Second,
},
Notifier: &notification.Config{
Attempts: 5,
RenotifyInterval: 2 * time.Hour,
},
}
}
// LoadConfig is a shortcut to open a file, read it, and generate a Config.
//
// It supports relative and absolute paths. Given "", it returns DefaultConfig.
func LoadConfig(path string) (config *Config, err error) {
var cfgFile File
cfgFile.Clair = DefaultConfig()
if path == "" {
return &cfgFile.Clair, nil
}
f, err := os.Open(os.ExpandEnv(path))
if err != nil {
return
}
defer f.Close()
d, err := ioutil.ReadAll(f)
if err != nil {
return
}
err = yaml.Unmarshal(d, &cfgFile)
if err != nil {
return
}
config = &cfgFile.Clair
// Generate a pagination key if none is provided.
if config.API.PaginationKey == "" {
var key fernet.Key
if err = key.Generate(); err != nil {
return
}
config.API.PaginationKey = key.Encode()
} else {
_, err = fernet.DecodeKey(config.API.PaginationKey)
if err != nil {
err = errors.New("Invalid Pagination key; must be 32-bit URL-safe base64")
return
}
}
return
}
func waitForSignals(signals ...os.Signal) {
interrupts := make(chan os.Signal, 1)
signal.Notify(interrupts, signals...)

80
config.yaml Normal file
View File

@ -0,0 +1,80 @@
# Copyright 2015 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.
# 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:
database:
# Database driver
type: pgsql
options:
# PostgreSQL Connection string
# https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
source: host=192.168.10.11 port=5432 user=postgres password=123456 sslmode=disable statement_timeout=60000
# 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.
cachesize: 16384
api:
# API server port
port: 6060
# Health server port
# This is an unencrypted endpoint useful for load balancers to check to healthiness of the clair server.
healthport: 6061
# Deadline before an API request will respond with a 503
timeout: 900s
# 32-bit URL-safe base64 key used to encrypt pagination tokens
# If one is not provided, it will be generated.
# Multiple clair instances in the same cluster need the same value.
paginationkey:
# Optional PKI configuration
# If you want to easily generate client certificates and CAs, try the following projects:
# https://github.com/coreos/etcd-ca
# https://github.com/cloudflare/cfssl
servername:
cafile:
keyfile:
certfile:
updater:
# Frequency the database will be updated with vulnerabilities from the default data sources
# The value 0 disables the updater entirely.
interval: 2h
notifier:
# Number of attempts before the notification is marked as failed to be sent
attempts: 3
# Duration before a failed notification is retried
renotifyinterval: 2h
http:
# Optional endpoint that will receive notifications via POST requests
endpoint:
# Optional PKI configuration
# If you want to easily generate client certificates and CAs, try the following projects:
# https://github.com/cloudflare/cfssl
# https://github.com/coreos/etcd-ca
servername:
cafile:
keyfile:
certfile:
# Optional HTTP Proxy: must be a valid URL (including the scheme).
proxy: