mirror of
https://github.com/project-zot/zot.git
synced 2026-06-15 20:07:55 +08:00
Added graphql api feature for image vulnerability scanning
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
package search
|
||||
|
||||
//go:generate go run github.com/99designs/gqlgen
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/anuvu/zot/pkg/log"
|
||||
|
||||
cveinfo "github.com/anuvu/zot/pkg/extensions/search/cve"
|
||||
"github.com/anuvu/zot/pkg/storage"
|
||||
) // THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.
|
||||
|
||||
// Resolver ...
|
||||
type Resolver struct {
|
||||
cveInfo *cveinfo.CveInfo
|
||||
imgStore *storage.ImageStore
|
||||
dir string
|
||||
}
|
||||
|
||||
// Query ...
|
||||
func (r *Resolver) Query() QueryResolver {
|
||||
return &queryResolver{r}
|
||||
}
|
||||
|
||||
type queryResolver struct{ *Resolver }
|
||||
|
||||
type cveDetail struct {
|
||||
Title string
|
||||
Description string
|
||||
Severity string
|
||||
PackageList []*PackageInfo
|
||||
}
|
||||
|
||||
// GetResolverConfig ...
|
||||
func GetResolverConfig(dir string, log log.Logger, imgstorage *storage.ImageStore) Config {
|
||||
config, err := cveinfo.NewTrivyConfig(dir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cve := &cveinfo.CveInfo{Log: log, CveTrivyConfig: config}
|
||||
|
||||
resConfig := &Resolver{cveInfo: cve, imgStore: imgstorage, dir: dir}
|
||||
|
||||
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)
|
||||
|
||||
r.cveInfo.Log.Info().Str("Scanning Image", image).Msg("")
|
||||
|
||||
cveResults, err := cveinfo.ScanImage(r.cveInfo.CveTrivyConfig)
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Msg("Error scanning image repository")
|
||||
|
||||
return &CVEResultForImage{}, err
|
||||
}
|
||||
|
||||
var copyImgTag string
|
||||
|
||||
if strings.Contains(image, ":") {
|
||||
copyImgTag = strings.Split(image, ":")[1]
|
||||
}
|
||||
|
||||
cveidMap := make(map[string]cveDetail)
|
||||
|
||||
for _, result := range cveResults {
|
||||
for _, vulnerability := range result.Vulnerabilities {
|
||||
pkgName := vulnerability.PkgName
|
||||
|
||||
installedVersion := vulnerability.InstalledVersion
|
||||
|
||||
var fixedVersion string
|
||||
if vulnerability.FixedVersion != "" {
|
||||
fixedVersion = vulnerability.FixedVersion
|
||||
} else {
|
||||
fixedVersion = "Not Specified"
|
||||
}
|
||||
|
||||
_, ok := cveidMap[vulnerability.VulnerabilityID]
|
||||
if ok {
|
||||
cveDetailStruct := cveidMap[vulnerability.VulnerabilityID]
|
||||
|
||||
pkgList := cveDetailStruct.PackageList
|
||||
|
||||
pkgList = append(pkgList,
|
||||
&PackageInfo{Name: &pkgName, InstalledVersion: &installedVersion, FixedVersion: &fixedVersion})
|
||||
|
||||
cveDetailStruct.PackageList = pkgList
|
||||
|
||||
cveidMap[vulnerability.VulnerabilityID] = cveDetailStruct
|
||||
} else {
|
||||
newPkgList := make([]*PackageInfo, 0)
|
||||
|
||||
newPkgList = append(newPkgList,
|
||||
&PackageInfo{Name: &pkgName, InstalledVersion: &installedVersion, FixedVersion: &fixedVersion})
|
||||
|
||||
cveidMap[vulnerability.VulnerabilityID] = cveDetail{Title: vulnerability.Title,
|
||||
Description: vulnerability.Description, Severity: vulnerability.Severity, PackageList: newPkgList}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cveids := []*Cve{}
|
||||
|
||||
for id, cveDetail := range cveidMap {
|
||||
vulID := id
|
||||
|
||||
desc := cveDetail.Description
|
||||
|
||||
title := cveDetail.Title
|
||||
|
||||
severity := cveDetail.Severity
|
||||
|
||||
pkgList := cveDetail.PackageList
|
||||
|
||||
cveids = append(cveids,
|
||||
&Cve{ID: &vulID, Title: &title, Description: &desc, Severity: &severity, PackageList: pkgList})
|
||||
}
|
||||
|
||||
return &CVEResultForImage{Tag: ©ImgTag, CVEList: cveids}, nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) ImageListForCve(ctx context.Context, id string) ([]*ImgResultForCve, error) {
|
||||
cveResult := []*ImgResultForCve{}
|
||||
|
||||
r.cveInfo.Log.Info().Msg("Extracting Repositories")
|
||||
|
||||
repoList, err := r.imgStore.GetRepositories()
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Msg("Not able to search repositories")
|
||||
|
||||
return cveResult, err
|
||||
}
|
||||
|
||||
r.cveInfo.Log.Info().Msg("Scanning each repository")
|
||||
|
||||
for _, repo := range repoList {
|
||||
r.cveInfo.Log.Info().Str("Extracting list of tags available in image", repo).Msg("")
|
||||
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Str("Error reading image media type", repo)
|
||||
|
||||
return cveResult, err
|
||||
}
|
||||
|
||||
tagList, err := r.imgStore.GetImageTags(repo)
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Msg("Not able to get list of Image Tag")
|
||||
}
|
||||
|
||||
var name string
|
||||
|
||||
tags := make([]*string, 0)
|
||||
|
||||
for _, tag := range tagList {
|
||||
r.cveInfo.CveTrivyConfig.TrivyConfig.Input = path.Join(r.dir, repo+":"+tag)
|
||||
|
||||
r.cveInfo.Log.Info().Str("Scanning Image", path.Join(r.dir, repo+":"+tag)).Msg("")
|
||||
|
||||
results, err := cveinfo.ScanImage(r.cveInfo.CveTrivyConfig)
|
||||
if err != nil {
|
||||
r.cveInfo.Log.Error().Err(err).Str("Error scanning image", repo+":"+tag)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
name = repo
|
||||
|
||||
for _, result := range results {
|
||||
for _, vulnerability := range result.Vulnerabilities {
|
||||
if vulnerability.VulnerabilityID == id {
|
||||
copyImgTag := tag
|
||||
tags = append(tags, ©ImgTag)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(tags) != 0 {
|
||||
cveResult = append(cveResult, &ImgResultForCve{Name: &name, Tags: tags})
|
||||
}
|
||||
}
|
||||
|
||||
return cveResult, nil
|
||||
}
|
||||
Reference in New Issue
Block a user