mirror of
https://github.com/project-zot/zot.git
synced 2026-06-16 04:17:55 +08:00
config: support multiple storage locations
added support to point multiple storage locations in zot by running multiple instance of zot in background. see examples/config-multiple.json for more info about config. Closes #181
This commit is contained in:
committed by
Ramkumar Chinchani
parent
9ca6eea940
commit
28974e81dc
@@ -55,9 +55,9 @@ func EnableExtensions(extension *ExtensionConfig, log log.Logger, rootDir string
|
||||
}
|
||||
|
||||
// SetupRoutes ...
|
||||
func SetupRoutes(router *mux.Router, rootDir string, imgStore *storage.ImageStore, log log.Logger) {
|
||||
func SetupRoutes(router *mux.Router, storeController storage.StoreController, log log.Logger) {
|
||||
log.Info().Msg("setting up extensions routes")
|
||||
resConfig := search.GetResolverConfig(rootDir, log, imgStore)
|
||||
resConfig := search.GetResolverConfig(log, storeController)
|
||||
router.PathPrefix("/query").Methods("GET", "POST").
|
||||
Handler(gqlHandler.NewDefaultServer(search.NewExecutableSchema(resConfig)))
|
||||
}
|
||||
|
||||
@@ -21,6 +21,6 @@ func EnableExtensions(extension *ExtensionConfig, log log.Logger, rootDir string
|
||||
}
|
||||
|
||||
// SetupRoutes ...
|
||||
func SetupRoutes(router *mux.Router, rootDir string, imgStore *storage.ImageStore, log log.Logger) {
|
||||
func SetupRoutes(router *mux.Router, storeController storage.StoreController, log log.Logger) {
|
||||
log.Warn().Msg("skipping setting up extensions routes because given zot binary doesn't support any extensions, please build zot full binary for this feature")
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package cveinfo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
|
||||
"github.com/anuvu/zot/errors"
|
||||
"github.com/anuvu/zot/pkg/log"
|
||||
"github.com/anuvu/zot/pkg/storage"
|
||||
integration "github.com/aquasecurity/trivy/integration"
|
||||
config "github.com/aquasecurity/trivy/integration/config"
|
||||
"github.com/aquasecurity/trivy/pkg/report"
|
||||
@@ -44,6 +46,84 @@ func ScanImage(config *config.Config) (report.Results, error) {
|
||||
return integration.ScanTrivyImage(config.TrivyConfig)
|
||||
}
|
||||
|
||||
func GetCVEInfo(storeController storage.StoreController, log log.Logger) (*CveInfo, error) {
|
||||
cveController := CveTrivyController{}
|
||||
|
||||
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
|
||||
|
||||
return &CveInfo{Log: log, CveTrivyController: cveController, StoreController: storeController}, nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func (cveinfo CveInfo) IsValidImageFormat(imagePath string) (bool, error) {
|
||||
imageDir, inputTag := getImageDirAndTag(imagePath)
|
||||
|
||||
@@ -113,16 +193,85 @@ func getImageDirAndTag(imageName string) (string, string) {
|
||||
return imageDir, imageTag
|
||||
}
|
||||
|
||||
// Below method will return image path including root dir, root dir is determined by splitting.
|
||||
func (cveinfo CveInfo) GetImageRepoPath(image string) string {
|
||||
var rootDir string
|
||||
|
||||
prefixName := getRoutePrefix(image)
|
||||
|
||||
subStore := cveinfo.StoreController.SubStore
|
||||
|
||||
if subStore != nil {
|
||||
imgStore, ok := cveinfo.StoreController.SubStore[prefixName]
|
||||
if ok {
|
||||
rootDir = imgStore.RootDir()
|
||||
} else {
|
||||
rootDir = cveinfo.StoreController.DefaultStore.RootDir()
|
||||
}
|
||||
} else {
|
||||
rootDir = cveinfo.StoreController.DefaultStore.RootDir()
|
||||
}
|
||||
|
||||
return path.Join(rootDir, image)
|
||||
}
|
||||
|
||||
func (cveinfo CveInfo) GetImageListForCVE(repo string, id string, imgStore *storage.ImageStore,
|
||||
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)
|
||||
|
||||
isValidImage, _ := cveinfo.IsValidImageFormat(trivyConfig.TrivyConfig.Input)
|
||||
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
|
||||
}
|
||||
|
||||
// GetImageTagsWithTimestamp returns a list of image tags with timestamp available in the specified repository.
|
||||
func (cveinfo CveInfo) GetImageTagsWithTimestamp(rootDir string, repo string) ([]TagInfo, error) {
|
||||
func (cveinfo CveInfo) GetImageTagsWithTimestamp(repo string) ([]TagInfo, error) {
|
||||
tagsInfo := make([]TagInfo, 0)
|
||||
|
||||
dir := path.Join(rootDir, repo)
|
||||
if !dirExists(dir) {
|
||||
imagePath := cveinfo.GetImageRepoPath(repo)
|
||||
if !dirExists(imagePath) {
|
||||
return nil, errors.ErrRepoNotFound
|
||||
}
|
||||
|
||||
manifests, err := cveinfo.getImageManifests(dir)
|
||||
manifests, err := cveinfo.getImageManifests(imagePath)
|
||||
|
||||
if err != nil {
|
||||
cveinfo.Log.Error().Err(err).Msg("unable to read image manifests")
|
||||
@@ -135,7 +284,7 @@ func (cveinfo CveInfo) GetImageTagsWithTimestamp(rootDir string, repo string) ([
|
||||
|
||||
v, ok := manifest.Annotations[ispec.AnnotationRefName]
|
||||
if ok {
|
||||
imageBlobManifest, err := cveinfo.getImageBlobManifest(dir, digest)
|
||||
imageBlobManifest, err := cveinfo.getImageBlobManifest(imagePath, digest)
|
||||
|
||||
if err != nil {
|
||||
cveinfo.Log.Error().Err(err).Msg("unable to read image blob manifest")
|
||||
@@ -143,7 +292,7 @@ func (cveinfo CveInfo) GetImageTagsWithTimestamp(rootDir string, repo string) ([
|
||||
return tagsInfo, err
|
||||
}
|
||||
|
||||
imageInfo, err := cveinfo.getImageInfo(dir, imageBlobManifest.Config.Digest)
|
||||
imageInfo, err := cveinfo.getImageInfo(imagePath, imageBlobManifest.Config.Digest)
|
||||
if err != nil {
|
||||
cveinfo.Log.Error().Err(err).Msg("unable to read image info")
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
ext "github.com/anuvu/zot/pkg/extensions"
|
||||
cveinfo "github.com/anuvu/zot/pkg/extensions/search/cve"
|
||||
"github.com/anuvu/zot/pkg/log"
|
||||
"github.com/anuvu/zot/pkg/storage"
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"gopkg.in/resty.v1"
|
||||
@@ -23,8 +24,9 @@ import (
|
||||
|
||||
// nolint:gochecknoglobals
|
||||
var (
|
||||
cve *cveinfo.CveInfo
|
||||
dbDir string
|
||||
cve *cveinfo.CveInfo
|
||||
dbDir string
|
||||
updateDuration time.Duration
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -76,7 +78,11 @@ func testSetup() error {
|
||||
return err
|
||||
}
|
||||
|
||||
cve = &cveinfo.CveInfo{Log: log.NewLogger("debug", "")}
|
||||
log := log.NewLogger("debug", "")
|
||||
|
||||
cve = &cveinfo.CveInfo{Log: log}
|
||||
|
||||
cve.StoreController = storage.StoreController{DefaultStore: storage.NewImageStore(dir, false, false, log)}
|
||||
|
||||
dbDir = dir
|
||||
|
||||
@@ -365,6 +371,67 @@ func makeHtpasswdFile() string {
|
||||
return f.Name()
|
||||
}
|
||||
|
||||
func TestMultipleStoragePath(t *testing.T) {
|
||||
Convey("Test multiple storage path", t, func() {
|
||||
// Create temporary directory
|
||||
firstRootDir, err := ioutil.TempDir("", "util_test")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer os.RemoveAll(firstRootDir)
|
||||
|
||||
secondRootDir, err := ioutil.TempDir("", "util_test")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer os.RemoveAll(secondRootDir)
|
||||
|
||||
thirdRootDir, err := ioutil.TempDir("", "util_test")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer os.RemoveAll(thirdRootDir)
|
||||
|
||||
log := log.NewLogger("debug", "")
|
||||
|
||||
// Create ImageStore
|
||||
firstStore := storage.NewImageStore(firstRootDir, false, false, log)
|
||||
|
||||
secondStore := storage.NewImageStore(secondRootDir, false, false, log)
|
||||
|
||||
thirdStore := storage.NewImageStore(thirdRootDir, false, false, log)
|
||||
|
||||
storeController := storage.StoreController{}
|
||||
|
||||
storeController.DefaultStore = firstStore
|
||||
|
||||
subStore := make(map[string]*storage.ImageStore)
|
||||
|
||||
subStore["/a"] = secondStore
|
||||
subStore["/b"] = thirdStore
|
||||
|
||||
storeController.SubStore = subStore
|
||||
|
||||
cveInfo, err := cveinfo.GetCVEInfo(storeController, log)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(cveInfo.StoreController.DefaultStore, ShouldNotBeNil)
|
||||
So(cveInfo.StoreController.SubStore, ShouldNotBeNil)
|
||||
|
||||
imagePath := cveInfo.GetImageRepoPath("zot-test")
|
||||
So(imagePath, ShouldEqual, path.Join(firstRootDir, "zot-test"))
|
||||
|
||||
imagePath = cveInfo.GetImageRepoPath("a/zot-a-test")
|
||||
So(imagePath, ShouldEqual, path.Join(secondRootDir, "a/zot-a-test"))
|
||||
|
||||
imagePath = cveInfo.GetImageRepoPath("b/zot-b-test")
|
||||
So(imagePath, ShouldEqual, path.Join(thirdRootDir, "b/zot-b-test"))
|
||||
|
||||
imagePath = cveInfo.GetImageRepoPath("c/zot-c-test")
|
||||
So(imagePath, ShouldEqual, path.Join(firstRootDir, "c/zot-c-test"))
|
||||
})
|
||||
}
|
||||
|
||||
func TestDownloadDB(t *testing.T) {
|
||||
Convey("Download DB passing invalid dir", t, func() {
|
||||
err := testSetup()
|
||||
@@ -425,35 +492,35 @@ func TestImageFormat(t *testing.T) {
|
||||
|
||||
func TestImageTag(t *testing.T) {
|
||||
Convey("Test image tag", t, func() {
|
||||
imageTags, err := cve.GetImageTagsWithTimestamp(dbDir, "zot-test")
|
||||
imageTags, err := cve.GetImageTagsWithTimestamp("zot-test")
|
||||
So(err, ShouldBeNil)
|
||||
So(len(imageTags), ShouldNotEqual, 0)
|
||||
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp(dbDir, "zot-tes")
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp("zot-tes")
|
||||
So(err, ShouldNotBeNil)
|
||||
So(imageTags, ShouldBeNil)
|
||||
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp(dbDir, "zot-noindex-test")
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp("zot-noindex-test")
|
||||
So(err, ShouldNotBeNil)
|
||||
So(len(imageTags), ShouldEqual, 0)
|
||||
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp(dbDir, "zot-squashfs-noblobs")
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp("zot-squashfs-noblobs")
|
||||
So(err, ShouldNotBeNil)
|
||||
So(len(imageTags), ShouldEqual, 0)
|
||||
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp(dbDir, "zot-squashfs-invalid-index")
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp("zot-squashfs-invalid-index")
|
||||
So(err, ShouldNotBeNil)
|
||||
So(len(imageTags), ShouldEqual, 0)
|
||||
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp(dbDir, "zot-squashfs-invalid-blob")
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp("zot-squashfs-invalid-blob")
|
||||
So(err, ShouldNotBeNil)
|
||||
So(len(imageTags), ShouldEqual, 0)
|
||||
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp(dbDir, "zot-invalid-layer")
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp("zot-invalid-layer")
|
||||
So(err, ShouldNotBeNil)
|
||||
So(len(imageTags), ShouldEqual, 0)
|
||||
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp(dbDir, "zot-no-layer")
|
||||
imageTags, err = cve.GetImageTagsWithTimestamp("zot-no-layer")
|
||||
So(err, ShouldNotBeNil)
|
||||
So(len(imageTags), ShouldEqual, 0)
|
||||
})
|
||||
@@ -461,7 +528,7 @@ func TestImageTag(t *testing.T) {
|
||||
|
||||
func TestCVESearch(t *testing.T) {
|
||||
Convey("Test image vulenrability scanning", t, func() {
|
||||
updateDuration, _ := time.ParseDuration("1h")
|
||||
updateDuration, _ = time.ParseDuration("1h")
|
||||
config := api.NewConfig()
|
||||
config.HTTP.Port = SecurePort1
|
||||
htpasswdPath := makeHtpasswdFile()
|
||||
@@ -473,7 +540,6 @@ func TestCVESearch(t *testing.T) {
|
||||
},
|
||||
}
|
||||
c := api.NewController(config)
|
||||
defer os.RemoveAll(dbDir)
|
||||
c.Config.Storage.RootDirectory = dbDir
|
||||
cveConfig := &ext.CVEConfig{
|
||||
UpdateInterval: updateDuration,
|
||||
@@ -698,13 +764,30 @@ func TestCVEConfig(t *testing.T) {
|
||||
},
|
||||
}
|
||||
c := api.NewController(config)
|
||||
dir, err := ioutil.TempDir("", "oci-repo-test")
|
||||
firstDir, err := ioutil.TempDir("", "oci-repo-test")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
c.Config.Storage.RootDirectory = dir
|
||||
c.Config.Extensions = &ext.ExtensionConfig{}
|
||||
|
||||
secondDir, err := ioutil.TempDir("", "oci-repo-test")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer os.RemoveAll(firstDir)
|
||||
defer os.RemoveAll(secondDir)
|
||||
|
||||
err = copyFiles("../../../../test/data", path.Join(secondDir, "a"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c.Config.Storage.RootDirectory = firstDir
|
||||
subPaths := make(map[string]api.StorageConfig)
|
||||
subPaths["/a"] = api.StorageConfig{
|
||||
RootDirectory: secondDir,
|
||||
}
|
||||
c.Config.Storage.SubPaths = subPaths
|
||||
|
||||
go func() {
|
||||
// this blocks
|
||||
if err := c.Run(); err != nil {
|
||||
@@ -721,6 +804,22 @@ func TestCVEConfig(t *testing.T) {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
resp, _ := resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/v2/")
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/v2/_catalog")
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/v2/a/zot-test/tags/list")
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/v2/zot-test/tags/list")
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 404)
|
||||
|
||||
defer func() {
|
||||
ctx := context.Background()
|
||||
_ = c.Server.Shutdown(ctx)
|
||||
|
||||
@@ -5,13 +5,20 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/anuvu/zot/pkg/log"
|
||||
"github.com/anuvu/zot/pkg/storage"
|
||||
config "github.com/aquasecurity/trivy/integration/config"
|
||||
)
|
||||
|
||||
// CveInfo ...
|
||||
type CveInfo struct {
|
||||
Log log.Logger
|
||||
CveTrivyConfig *config.Config
|
||||
Log log.Logger
|
||||
CveTrivyController CveTrivyController
|
||||
StoreController storage.StoreController
|
||||
}
|
||||
|
||||
type CveTrivyController struct {
|
||||
DefaultCveConfig *config.Config
|
||||
SubCveConfig map[string]*config.Config
|
||||
}
|
||||
|
||||
type TagInfo struct {
|
||||
|
||||
@@ -4,10 +4,11 @@ package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/anuvu/zot/pkg/log"
|
||||
"github.com/aquasecurity/trivy/integration/config"
|
||||
|
||||
cveinfo "github.com/anuvu/zot/pkg/extensions/search/cve"
|
||||
"github.com/anuvu/zot/pkg/storage"
|
||||
@@ -15,9 +16,8 @@ import (
|
||||
|
||||
// Resolver ...
|
||||
type Resolver struct {
|
||||
cveInfo *cveinfo.CveInfo
|
||||
imgStore *storage.ImageStore
|
||||
dir string
|
||||
cveInfo *cveinfo.CveInfo
|
||||
storeController storage.StoreController
|
||||
}
|
||||
|
||||
// Query ...
|
||||
@@ -35,33 +35,31 @@ type cveDetail struct {
|
||||
}
|
||||
|
||||
// GetResolverConfig ...
|
||||
func GetResolverConfig(dir string, log log.Logger, imgstorage *storage.ImageStore) Config {
|
||||
config, err := cveinfo.NewTrivyConfig(dir)
|
||||
func GetResolverConfig(log log.Logger, storeController storage.StoreController) Config {
|
||||
cveInfo, err := cveinfo.GetCVEInfo(storeController, log)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cve := &cveinfo.CveInfo{Log: log, CveTrivyConfig: config}
|
||||
|
||||
resConfig := &Resolver{cveInfo: cve, imgStore: imgstorage, dir: dir}
|
||||
resConfig := &Resolver{cveInfo: cveInfo, storeController: storeController}
|
||||
|
||||
return Config{Resolvers: resConfig, Directives: DirectiveRoot{},
|
||||
Complexity: ComplexityRoot{}}
|
||||
}
|
||||
|
||||
func (r *queryResolver) CVEListForImage(ctx context.Context, image string) (*CVEResultForImage, error) {
|
||||
r.cveInfo.CveTrivyConfig.TrivyConfig.Input = path.Join(r.dir, image)
|
||||
trivyConfig := r.cveInfo.GetTrivyConfig(image)
|
||||
|
||||
r.cveInfo.Log.Info().Str("image", image).Msg("scanning image")
|
||||
|
||||
isValidImage, err := r.cveInfo.IsValidImageFormat(r.cveInfo.CveTrivyConfig.TrivyConfig.Input)
|
||||
isValidImage, err := r.cveInfo.IsValidImageFormat(trivyConfig.TrivyConfig.Input)
|
||||
if !isValidImage {
|
||||
r.cveInfo.Log.Debug().Str("image", image).Msg("image media type not supported for scanning")
|
||||
|
||||
return &CVEResultForImage{}, err
|
||||
}
|
||||
|
||||
cveResults, err := cveinfo.ScanImage(r.cveInfo.CveTrivyConfig)
|
||||
cveResults, err := cveinfo.ScanImage(trivyConfig)
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Msg("unable to scan image repository")
|
||||
|
||||
@@ -134,62 +132,70 @@ func (r *queryResolver) CVEListForImage(ctx context.Context, image string) (*CVE
|
||||
}
|
||||
|
||||
func (r *queryResolver) ImageListForCve(ctx context.Context, id string) ([]*ImgResultForCve, error) {
|
||||
cveResult := []*ImgResultForCve{}
|
||||
finalCveResult := []*ImgResultForCve{}
|
||||
|
||||
r.cveInfo.Log.Info().Msg("extracting repositories")
|
||||
|
||||
repoList, err := r.imgStore.GetRepositories()
|
||||
defaultStore := r.storeController.DefaultStore
|
||||
|
||||
defaultTrivyConfig := r.cveInfo.CveTrivyController.DefaultCveConfig
|
||||
|
||||
repoList, err := defaultStore.GetRepositories()
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Msg("unable to search repositories")
|
||||
|
||||
return cveResult, err
|
||||
return finalCveResult, err
|
||||
}
|
||||
|
||||
r.cveInfo.Log.Info().Msg("scanning each repository")
|
||||
r.cveInfo.Log.Info().Msg("scanning each global repository")
|
||||
|
||||
cveResult, err := r.getImageListForCVE(repoList, id, defaultStore, defaultTrivyConfig)
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Msg("error getting cve list for global repositories")
|
||||
|
||||
return finalCveResult, err
|
||||
}
|
||||
|
||||
finalCveResult = append(finalCveResult, cveResult...)
|
||||
|
||||
subStore := r.storeController.SubStore
|
||||
for route, store := range subStore {
|
||||
subRepoList, err := store.GetRepositories()
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Msg("unable to search repositories")
|
||||
|
||||
return cveResult, err
|
||||
}
|
||||
|
||||
subTrivyConfig := r.cveInfo.CveTrivyController.SubCveConfig[route]
|
||||
|
||||
subCveResult, err := r.getImageListForCVE(subRepoList, id, store, subTrivyConfig)
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Msg("unable to get cve result for sub repositories")
|
||||
|
||||
return finalCveResult, err
|
||||
}
|
||||
|
||||
finalCveResult = append(finalCveResult, subCveResult...)
|
||||
}
|
||||
|
||||
return finalCveResult, nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) getImageListForCVE(repoList []string, id string, imgStore *storage.ImageStore,
|
||||
trivyConfig *config.Config) ([]*ImgResultForCve, error) {
|
||||
cveResult := []*ImgResultForCve{}
|
||||
|
||||
for _, repo := range repoList {
|
||||
r.cveInfo.Log.Info().Str("repo", repo).Msg("extracting list of tags available in image repo")
|
||||
|
||||
tagList, err := r.imgStore.GetImageTags(repo)
|
||||
name := repo
|
||||
|
||||
tags, err := r.cveInfo.GetImageListForCVE(repo, id, imgStore, trivyConfig)
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Msg("unable to get list of image tag")
|
||||
}
|
||||
r.cveInfo.Log.Error().Err(err).Msg("error getting tag")
|
||||
|
||||
var name string
|
||||
|
||||
tags := make([]*string, 0)
|
||||
|
||||
for _, tag := range tagList {
|
||||
r.cveInfo.CveTrivyConfig.TrivyConfig.Input = path.Join(r.dir, repo+":"+tag)
|
||||
|
||||
isValidImage, _ := r.cveInfo.IsValidImageFormat(r.cveInfo.CveTrivyConfig.TrivyConfig.Input)
|
||||
if !isValidImage {
|
||||
r.cveInfo.Log.Debug().Str("image", repo+":"+tag).Msg("image media type not supported for scanning")
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
r.cveInfo.Log.Info().Str("image", repo+":"+tag).Msg("scanning image")
|
||||
|
||||
results, err := cveinfo.ScanImage(r.cveInfo.CveTrivyConfig)
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Str("image", repo+":"+tag).Msg("unable to scan image")
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
name = repo
|
||||
|
||||
for _, result := range results {
|
||||
for _, vulnerability := range result.Vulnerabilities {
|
||||
if vulnerability.VulnerabilityID == id {
|
||||
copyImgTag := tag
|
||||
tags = append(tags, ©ImgTag)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return cveResult, err
|
||||
}
|
||||
|
||||
if len(tags) != 0 {
|
||||
@@ -203,9 +209,17 @@ func (r *queryResolver) ImageListForCve(ctx context.Context, id string) ([]*ImgR
|
||||
func (r *queryResolver) ImageListWithCVEFixed(ctx context.Context, id string, image string) (*ImgResultForFixedCve, error) { // nolint: lll
|
||||
imgResultForFixedCVE := &ImgResultForFixedCve{}
|
||||
|
||||
r.cveInfo.Log.Info().Str("image", image).Msg("retrieving image path")
|
||||
|
||||
imagePath := r.cveInfo.GetImageRepoPath(image)
|
||||
|
||||
r.cveInfo.Log.Info().Str("image", image).Msg("retrieving trivy config")
|
||||
|
||||
trivyConfig := r.cveInfo.GetTrivyConfig(image)
|
||||
|
||||
r.cveInfo.Log.Info().Str("image", image).Msg("extracting list of tags available in image")
|
||||
|
||||
tagsInfo, err := r.cveInfo.GetImageTagsWithTimestamp(r.dir, image)
|
||||
tagsInfo, err := r.cveInfo.GetImageTagsWithTimestamp(image)
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Msg("unable to read image tags")
|
||||
|
||||
@@ -217,9 +231,9 @@ func (r *queryResolver) ImageListWithCVEFixed(ctx context.Context, id string, im
|
||||
var hasCVE bool
|
||||
|
||||
for _, tag := range tagsInfo {
|
||||
r.cveInfo.CveTrivyConfig.TrivyConfig.Input = path.Join(r.dir, image+":"+tag.Name)
|
||||
trivyConfig.TrivyConfig.Input = fmt.Sprintf("%s:%s", imagePath, tag.Name)
|
||||
|
||||
isValidImage, _ := r.cveInfo.IsValidImageFormat(r.cveInfo.CveTrivyConfig.TrivyConfig.Input)
|
||||
isValidImage, _ := r.cveInfo.IsValidImageFormat(trivyConfig.TrivyConfig.Input)
|
||||
if !isValidImage {
|
||||
r.cveInfo.Log.Debug().Str("image",
|
||||
image+":"+tag.Name).Msg("image media type not supported for scanning, adding as an infected image")
|
||||
@@ -231,7 +245,7 @@ func (r *queryResolver) ImageListWithCVEFixed(ctx context.Context, id string, im
|
||||
|
||||
r.cveInfo.Log.Info().Str("image", image+":"+tag.Name).Msg("scanning image")
|
||||
|
||||
results, err := cveinfo.ScanImage(r.cveInfo.CveTrivyConfig)
|
||||
results, err := cveinfo.ScanImage(trivyConfig)
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Str("image", image+":"+tag.Name).Msg("unable to scan image")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user