2020-06-24 14:38:42 -05:00
|
|
|
package cveinfo
|
|
|
|
|
|
|
|
import (
|
2021-04-05 19:40:33 -05:00
|
|
|
"fmt"
|
2020-08-19 01:03:16 -05:00
|
|
|
"path"
|
|
|
|
"strings"
|
|
|
|
|
2021-05-26 12:22:31 -05:00
|
|
|
"github.com/anuvu/zot/pkg/extensions/search/common"
|
2020-06-24 14:38:42 -05:00
|
|
|
"github.com/anuvu/zot/pkg/log"
|
2021-04-05 19:40:33 -05:00
|
|
|
"github.com/anuvu/zot/pkg/storage"
|
2020-06-24 14:38:42 -05:00
|
|
|
integration "github.com/aquasecurity/trivy/integration"
|
|
|
|
config "github.com/aquasecurity/trivy/integration/config"
|
2020-06-26 14:09:10 -05:00
|
|
|
"github.com/aquasecurity/trivy/pkg/report"
|
2020-06-24 14:38:42 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
// UpdateCVEDb ...
|
|
|
|
func UpdateCVEDb(dbDir string, log log.Logger) error {
|
|
|
|
config, err := config.NewConfig(dbDir)
|
|
|
|
if err != nil {
|
2020-09-22 12:35:39 -05:00
|
|
|
log.Error().Err(err).Msg("unable to get config")
|
2020-06-24 14:38:42 -05:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = integration.RunTrivyDb(config.TrivyConfig)
|
|
|
|
if err != nil {
|
2020-09-22 12:35:39 -05:00
|
|
|
log.Error().Err(err).Msg("unable to update DB ")
|
2020-06-24 14:38:42 -05:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2020-06-26 14:09:10 -05:00
|
|
|
|
|
|
|
func NewTrivyConfig(dir string) (*config.Config, error) {
|
|
|
|
return config.NewConfig(dir)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ScanImage(config *config.Config) (report.Results, error) {
|
|
|
|
return integration.ScanTrivyImage(config.TrivyConfig)
|
|
|
|
}
|
2020-08-19 01:03:16 -05:00
|
|
|
|
2021-04-05 19:40:33 -05:00
|
|
|
func GetCVEInfo(storeController storage.StoreController, log log.Logger) (*CveInfo, error) {
|
|
|
|
cveController := CveTrivyController{}
|
2021-09-30 08:27:13 -05:00
|
|
|
layoutUtils := common.NewOciLayoutUtils(storeController, log)
|
2021-04-05 19:40:33 -05:00
|
|
|
|
|
|
|
subCveConfig := make(map[string]*config.Config)
|
|
|
|
|
|
|
|
if storeController.DefaultStore != nil {
|
|
|
|
imageStore := storeController.DefaultStore
|
|
|
|
|
|
|
|
rootDir := imageStore.RootDir()
|
|
|
|
|
|
|
|
config, err := NewTrivyConfig(rootDir)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
cveController.DefaultCveConfig = config
|
|
|
|
}
|
|
|
|
|
|
|
|
if storeController.SubStore != nil {
|
|
|
|
for route, storage := range storeController.SubStore {
|
|
|
|
rootDir := storage.RootDir()
|
|
|
|
|
|
|
|
config, err := NewTrivyConfig(rootDir)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
subCveConfig[route] = config
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cveController.SubCveConfig = subCveConfig
|
|
|
|
|
2021-05-26 12:22:31 -05:00
|
|
|
return &CveInfo{Log: log, CveTrivyController: cveController, StoreController: storeController,
|
|
|
|
LayoutUtils: layoutUtils}, nil
|
2021-04-05 19:40:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func getRoutePrefix(name string) string {
|
|
|
|
names := strings.SplitN(name, "/", 2)
|
|
|
|
|
|
|
|
if len(names) != 2 { // nolint: gomnd
|
|
|
|
// it means route is of global storage e.g "centos:latest"
|
|
|
|
if len(names) == 1 {
|
|
|
|
return "/"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Sprintf("/%s", names[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cveinfo CveInfo) GetTrivyConfig(image string) *config.Config {
|
|
|
|
// Split image to get route prefix
|
|
|
|
prefixName := getRoutePrefix(image)
|
|
|
|
|
|
|
|
var trivyConfig *config.Config
|
|
|
|
|
|
|
|
var ok bool
|
|
|
|
|
|
|
|
var rootDir string
|
|
|
|
|
|
|
|
// Get corresponding CVE trivy config, if no sub cve config present that means its default
|
|
|
|
trivyConfig, ok = cveinfo.CveTrivyController.SubCveConfig[prefixName]
|
|
|
|
if ok {
|
|
|
|
imgStore := cveinfo.StoreController.SubStore[prefixName]
|
|
|
|
|
|
|
|
rootDir = imgStore.RootDir()
|
|
|
|
} else {
|
|
|
|
trivyConfig = cveinfo.CveTrivyController.DefaultCveConfig
|
|
|
|
|
|
|
|
imgStore := cveinfo.StoreController.DefaultStore
|
|
|
|
|
|
|
|
rootDir = imgStore.RootDir()
|
|
|
|
}
|
|
|
|
|
|
|
|
trivyConfig.TrivyConfig.Input = path.Join(rootDir, image)
|
|
|
|
|
|
|
|
return trivyConfig
|
|
|
|
}
|
|
|
|
|
2021-09-30 08:27:13 -05:00
|
|
|
func (cveinfo CveInfo) GetImageListForCVE(repo string, id string, imgStore storage.ImageStore,
|
2021-04-05 19:40:33 -05:00
|
|
|
trivyConfig *config.Config) ([]*string, error) {
|
|
|
|
tags := make([]*string, 0)
|
|
|
|
|
|
|
|
tagList, err := imgStore.GetImageTags(repo)
|
|
|
|
if err != nil {
|
|
|
|
cveinfo.Log.Error().Err(err).Msg("unable to get list of image tag")
|
|
|
|
|
|
|
|
return tags, err
|
|
|
|
}
|
|
|
|
|
|
|
|
rootDir := imgStore.RootDir()
|
|
|
|
|
|
|
|
for _, tag := range tagList {
|
|
|
|
trivyConfig.TrivyConfig.Input = fmt.Sprintf("%s:%s", path.Join(rootDir, repo), tag)
|
|
|
|
|
2021-09-30 08:27:13 -05:00
|
|
|
isValidImage, _ := cveinfo.LayoutUtils.IsValidImageFormat(fmt.Sprintf("%s:%s", repo, tag))
|
2021-04-05 19:40:33 -05:00
|
|
|
if !isValidImage {
|
|
|
|
cveinfo.Log.Debug().Str("image", repo+":"+tag).Msg("image media type not supported for scanning")
|
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
cveinfo.Log.Info().Str("image", repo+":"+tag).Msg("scanning image")
|
|
|
|
|
|
|
|
results, err := ScanImage(trivyConfig)
|
|
|
|
if err != nil {
|
|
|
|
cveinfo.Log.Error().Err(err).Str("image", repo+":"+tag).Msg("unable to scan image")
|
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, result := range results {
|
|
|
|
for _, vulnerability := range result.Vulnerabilities {
|
|
|
|
if vulnerability.VulnerabilityID == id {
|
|
|
|
copyImgTag := tag
|
|
|
|
tags = append(tags, ©ImgTag)
|
|
|
|
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tags, nil
|
|
|
|
}
|