mirror of
https://github.com/project-zot/zot.git
synced 2025-02-03 23:09:41 -05:00
bcdd9988f5
1. Only scan CVEs for images returned by graphql calls Since pagination was refactored to account for image indexes, we had started to run the CVE scanner before pagination was applied, resulting in decreased ZOT performance if CVE information was requested 2. Increase in medory-cache of cve results to 1m, from 10k digests. 3. Update CVE model to use CVSS severity values in our code. Previously we relied upon the strings returned by trivy directly, and the sorting they implemented. Since CVE severities are standardized, we don't need to pass around an adapter object just for pagination and sorting purposes anymore. This also improves our testing since we don't mock the sorting functions anymore. 4. Fix a flaky CLI test not waiting for the zot service to start. 5. Add the search build label on search/cve tests which were missing it. 6. The boltdb update method was used in a few places where view was supposed to be called. 7. Add logs for start and finish of parsing MetaDB. 8. Avoid unmarshalling twice to obtain annotations for multiarch images. Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
169 lines
6.8 KiB
Go
169 lines
6.8 KiB
Go
package search
|
|
|
|
// This file will be automatically regenerated based on the schema, any resolver implementations
|
|
// will be copied through when generating and any unknown code will be moved to the end.
|
|
// Code generated by github.com/99designs/gqlgen version v0.17.37
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/vektah/gqlparser/v2/gqlerror"
|
|
zerr "zotregistry.io/zot/errors"
|
|
"zotregistry.io/zot/pkg/common"
|
|
"zotregistry.io/zot/pkg/extensions/search/convert"
|
|
"zotregistry.io/zot/pkg/extensions/search/gql_generated"
|
|
)
|
|
|
|
// CVEListForImage is the resolver for the CVEListForImage field.
|
|
func (r *queryResolver) CVEListForImage(ctx context.Context, image string, requestedPage *gql_generated.PageInput, searchedCve *string) (*gql_generated.CVEResultForImage, error) {
|
|
if r.cveInfo == nil {
|
|
return &gql_generated.CVEResultForImage{}, zerr.ErrCVESearchDisabled
|
|
}
|
|
|
|
if searchedCve == nil {
|
|
return getCVEListForImage(ctx, image, r.cveInfo, requestedPage, "", r.log)
|
|
}
|
|
|
|
return getCVEListForImage(ctx, image, r.cveInfo, requestedPage, *searchedCve, r.log)
|
|
}
|
|
|
|
// ImageListForCve is the resolver for the ImageListForCVE field.
|
|
func (r *queryResolver) ImageListForCve(ctx context.Context, id string, filter *gql_generated.Filter, requestedPage *gql_generated.PageInput) (*gql_generated.PaginatedImagesResult, error) {
|
|
if r.cveInfo == nil {
|
|
return &gql_generated.PaginatedImagesResult{}, zerr.ErrCVESearchDisabled
|
|
}
|
|
|
|
filter = cleanFilter(filter)
|
|
|
|
return getImageListForCVE(ctx, id, r.cveInfo, filter, requestedPage, r.metaDB, r.log)
|
|
}
|
|
|
|
// ImageListWithCVEFixed is the resolver for the ImageListWithCVEFixed field.
|
|
func (r *queryResolver) ImageListWithCVEFixed(ctx context.Context, id string, image string, filter *gql_generated.Filter, requestedPage *gql_generated.PageInput) (*gql_generated.PaginatedImagesResult, error) {
|
|
if r.cveInfo == nil {
|
|
return &gql_generated.PaginatedImagesResult{}, zerr.ErrCVESearchDisabled
|
|
}
|
|
|
|
filter = cleanFilter(filter)
|
|
|
|
return getImageListWithCVEFixed(ctx, id, image, r.cveInfo, filter, requestedPage, r.metaDB, r.log)
|
|
}
|
|
|
|
// ImageListForDigest is the resolver for the ImageListForDigest field.
|
|
func (r *queryResolver) ImageListForDigest(ctx context.Context, id string, requestedPage *gql_generated.PageInput) (*gql_generated.PaginatedImagesResult, error) {
|
|
r.log.Info().Msg("extracting repositories")
|
|
|
|
imgResultForDigest, err := getImageListForDigest(ctx, id, r.metaDB, r.cveInfo, requestedPage)
|
|
|
|
return imgResultForDigest, err
|
|
}
|
|
|
|
// RepoListWithNewestImage is the resolver for the RepoListWithNewestImage field.
|
|
func (r *queryResolver) RepoListWithNewestImage(ctx context.Context, requestedPage *gql_generated.PageInput) (*gql_generated.PaginatedReposResult, error) {
|
|
r.log.Info().Msg("extension api: finding image list")
|
|
|
|
paginatedReposResult, err := repoListWithNewestImage(ctx, r.cveInfo, r.log, requestedPage, r.metaDB)
|
|
if err != nil {
|
|
r.log.Error().Err(err).Msg("unable to retrieve repo list")
|
|
|
|
return paginatedReposResult, err
|
|
}
|
|
|
|
return paginatedReposResult, nil
|
|
}
|
|
|
|
// ImageList is the resolver for the ImageList field.
|
|
func (r *queryResolver) ImageList(ctx context.Context, repo string, requestedPage *gql_generated.PageInput) (*gql_generated.PaginatedImagesResult, error) {
|
|
r.log.Info().Msg("extension api: getting a list of all images")
|
|
|
|
imageList, err := getImageList(ctx, repo, r.metaDB, r.cveInfo, requestedPage, r.log)
|
|
if err != nil {
|
|
r.log.Error().Err(err).Str("repository", repo).Msg("unable to retrieve image list for repo")
|
|
|
|
return imageList, err
|
|
}
|
|
|
|
return imageList, nil
|
|
}
|
|
|
|
// ExpandedRepoInfo is the resolver for the ExpandedRepoInfo field.
|
|
func (r *queryResolver) ExpandedRepoInfo(ctx context.Context, repo string) (*gql_generated.RepoInfo, error) {
|
|
repoInfo, err := expandedRepoInfo(ctx, repo, r.metaDB, r.cveInfo, r.log)
|
|
|
|
return repoInfo, err
|
|
}
|
|
|
|
// GlobalSearch is the resolver for the GlobalSearch field.
|
|
func (r *queryResolver) GlobalSearch(ctx context.Context, query string, filter *gql_generated.Filter, requestedPage *gql_generated.PageInput) (*gql_generated.GlobalSearchResult, error) {
|
|
if err := validateGlobalSearchInput(query, filter, requestedPage); err != nil {
|
|
return &gql_generated.GlobalSearchResult{}, err
|
|
}
|
|
|
|
query = cleanQuery(query)
|
|
filter = cleanFilter(filter)
|
|
|
|
paginatedReposResult, images, layers, err := globalSearch(ctx, query, r.metaDB, filter, requestedPage, r.cveInfo, r.log)
|
|
|
|
return &gql_generated.GlobalSearchResult{
|
|
Page: paginatedReposResult.Page,
|
|
Images: images,
|
|
Repos: paginatedReposResult.Results,
|
|
Layers: layers,
|
|
}, err
|
|
}
|
|
|
|
// DependencyListForImage is the resolver for the DependencyListForImage field.
|
|
func (r *queryResolver) DerivedImageList(ctx context.Context, image string, digest *string, requestedPage *gql_generated.PageInput) (*gql_generated.PaginatedImagesResult, error) {
|
|
derivedList, err := derivedImageList(ctx, image, digest, r.metaDB, requestedPage, r.cveInfo, r.log)
|
|
|
|
return derivedList, err
|
|
}
|
|
|
|
// BaseImageList is the resolver for the BaseImageList field.
|
|
func (r *queryResolver) BaseImageList(ctx context.Context, image string, digest *string, requestedPage *gql_generated.PageInput) (*gql_generated.PaginatedImagesResult, error) {
|
|
imageList, err := baseImageList(ctx, image, digest, r.metaDB, requestedPage, r.cveInfo, r.log)
|
|
|
|
return imageList, err
|
|
}
|
|
|
|
// Image is the resolver for the Image field.
|
|
func (r *queryResolver) Image(ctx context.Context, image string) (*gql_generated.ImageSummary, error) {
|
|
repo, tag := common.GetImageDirAndTag(image)
|
|
|
|
if tag == "" {
|
|
return &gql_generated.ImageSummary{}, gqlerror.Errorf("no reference provided")
|
|
}
|
|
|
|
skip := convert.SkipQGLField{
|
|
Vulnerabilities: canSkipField(convert.GetPreloads(ctx), "Vulnerabilities"),
|
|
}
|
|
|
|
return getImageSummary(ctx, repo, tag, nil, skip, r.metaDB, r.cveInfo, r.log)
|
|
}
|
|
|
|
// Referrers is the resolver for the Referrers field.
|
|
func (r *queryResolver) Referrers(ctx context.Context, repo string, digest string, typeArg []string) ([]*gql_generated.Referrer, error) {
|
|
referrers, err := getReferrers(r.metaDB, repo, digest, typeArg, r.log)
|
|
if err != nil {
|
|
r.log.Error().Err(err).Msg("unable to get referrers from default store")
|
|
|
|
return []*gql_generated.Referrer{}, err
|
|
}
|
|
|
|
return referrers, nil
|
|
}
|
|
|
|
// StarredRepos is the resolver for the StarredRepos field.
|
|
func (r *queryResolver) StarredRepos(ctx context.Context, requestedPage *gql_generated.PageInput) (*gql_generated.PaginatedReposResult, error) {
|
|
return getStarredRepos(ctx, r.cveInfo, r.log, requestedPage, r.metaDB)
|
|
}
|
|
|
|
// BookmarkedRepos is the resolver for the BookmarkedRepos field.
|
|
func (r *queryResolver) BookmarkedRepos(ctx context.Context, requestedPage *gql_generated.PageInput) (*gql_generated.PaginatedReposResult, error) {
|
|
return getBookmarkedRepos(ctx, r.cveInfo, r.log, requestedPage, r.metaDB)
|
|
}
|
|
|
|
// Query returns gql_generated.QueryResolver implementation.
|
|
func (r *Resolver) Query() gql_generated.QueryResolver { return &queryResolver{r} }
|
|
|
|
type queryResolver struct{ *Resolver }
|