zotregistry.io/zot@v1.4.4-0.20231124084042-02a8ed785457/pkg/extensions/search/convert/convert_internal_test.go (about)

     1  //go:build search
     2  
     3  package convert
     4  
     5  import (
     6  	"context"
     7  	"errors"
     8  	"testing"
     9  
    10  	"github.com/99designs/gqlgen/graphql"
    11  	ispec "github.com/opencontainers/image-spec/specs-go/v1"
    12  	. "github.com/smartystreets/goconvey/convey"
    13  
    14  	cvemodel "zotregistry.io/zot/pkg/extensions/search/cve/model"
    15  	"zotregistry.io/zot/pkg/extensions/search/gql_generated"
    16  	"zotregistry.io/zot/pkg/log"
    17  	"zotregistry.io/zot/pkg/meta/boltdb"
    18  	. "zotregistry.io/zot/pkg/test/image-utils"
    19  	"zotregistry.io/zot/pkg/test/mocks"
    20  )
    21  
    22  var ErrTestError = errors.New("TestError")
    23  
    24  func TestCVEConvert(t *testing.T) {
    25  	Convey("Test adding CVE information to Summary objects", t, func() {
    26  		params := boltdb.DBParameters{
    27  			RootDir: t.TempDir(),
    28  		}
    29  		boltDB, err := boltdb.GetBoltDriver(params)
    30  		So(err, ShouldBeNil)
    31  
    32  		metaDB, err := boltdb.New(boltDB, log.NewLogger("debug", ""))
    33  		So(err, ShouldBeNil)
    34  
    35  		image := CreateImageWith().
    36  			Layers([]Layer{{
    37  				MediaType: ispec.MediaTypeImageLayerGzip,
    38  				Digest:    ispec.MediaTypeEmptyJSON,
    39  				Blob:      ispec.DescriptorEmptyJSON.Data,
    40  			}}).DefaultConfig().Build()
    41  
    42  		err = metaDB.SetRepoReference(context.Background(), "repo1", "0.1.0", image.AsImageMeta())
    43  		So(err, ShouldBeNil)
    44  
    45  		repoMetaList, err := metaDB.SearchRepos(context.Background(), "")
    46  		So(err, ShouldBeNil)
    47  
    48  		imageMeta, err := metaDB.FilterImageMeta(context.Background(), []string{image.DigestStr()})
    49  
    50  		ctx := graphql.WithResponseContext(context.Background(),
    51  			graphql.DefaultErrorPresenter, graphql.DefaultRecover)
    52  
    53  		Convey("Add CVE Summary to ImageSummary", func() {
    54  			var imageSummary *gql_generated.ImageSummary
    55  
    56  			So(imageSummary, ShouldBeNil)
    57  
    58  			updateImageSummaryVulnerabilities(ctx,
    59  				imageSummary,
    60  				SkipQGLField{
    61  					Vulnerabilities: false,
    62  				},
    63  				mocks.CveInfoMock{
    64  					GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string,
    65  					) (cvemodel.ImageCVESummary, error) {
    66  						return cvemodel.ImageCVESummary{}, ErrTestError
    67  					},
    68  				},
    69  			)
    70  
    71  			So(imageSummary, ShouldBeNil)
    72  			So(graphql.GetErrors(ctx), ShouldBeNil)
    73  
    74  			imageSummary, _, err = ImageManifest2ImageSummary(ctx, GetFullImageMeta("0.1.0", repoMetaList[0],
    75  				imageMeta[image.DigestStr()]))
    76  			So(err, ShouldBeNil)
    77  
    78  			So(imageSummary, ShouldNotBeNil)
    79  			So(imageSummary.Vulnerabilities, ShouldBeNil)
    80  
    81  			updateImageSummaryVulnerabilities(ctx,
    82  				imageSummary,
    83  				SkipQGLField{
    84  					Vulnerabilities: true,
    85  				},
    86  				mocks.CveInfoMock{},
    87  			)
    88  
    89  			So(imageSummary.Vulnerabilities, ShouldNotBeNil)
    90  			So(*imageSummary.Vulnerabilities.Count, ShouldEqual, 0)
    91  			So(*imageSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "")
    92  			So(graphql.GetErrors(ctx), ShouldBeNil)
    93  
    94  			imageSummary.Vulnerabilities = nil
    95  
    96  			updateImageSummaryVulnerabilities(ctx,
    97  				imageSummary,
    98  				SkipQGLField{
    99  					Vulnerabilities: false,
   100  				},
   101  				mocks.CveInfoMock{
   102  					GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string,
   103  					) (cvemodel.ImageCVESummary, error) {
   104  						return cvemodel.ImageCVESummary{
   105  							Count:       1,
   106  							MaxSeverity: "HIGH",
   107  						}, nil
   108  					},
   109  				},
   110  			)
   111  
   112  			So(imageSummary.Vulnerabilities, ShouldNotBeNil)
   113  			So(*imageSummary.Vulnerabilities.Count, ShouldEqual, 1)
   114  			So(*imageSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "HIGH")
   115  			So(graphql.GetErrors(ctx), ShouldBeNil)
   116  			So(len(imageSummary.Manifests), ShouldEqual, 1)
   117  			So(imageSummary.Manifests[0].Vulnerabilities, ShouldNotBeNil)
   118  			So(*imageSummary.Manifests[0].Vulnerabilities.Count, ShouldEqual, 1)
   119  			So(*imageSummary.Manifests[0].Vulnerabilities.MaxSeverity, ShouldEqual, "HIGH")
   120  
   121  			imageSummary.Vulnerabilities = nil
   122  
   123  			updateImageSummaryVulnerabilities(ctx,
   124  				imageSummary,
   125  				SkipQGLField{
   126  					Vulnerabilities: false,
   127  				},
   128  				mocks.CveInfoMock{
   129  					GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string,
   130  					) (cvemodel.ImageCVESummary, error) {
   131  						return cvemodel.ImageCVESummary{}, ErrTestError
   132  					},
   133  				},
   134  			)
   135  
   136  			So(imageSummary.Vulnerabilities, ShouldNotBeNil)
   137  			So(*imageSummary.Vulnerabilities.Count, ShouldEqual, 0)
   138  			So(*imageSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "")
   139  			So(graphql.GetErrors(ctx).Error(), ShouldContainSubstring, "unable to run vulnerability scan on tag")
   140  		})
   141  
   142  		Convey("Add CVE Summary to RepoSummary", func() {
   143  			var repoSummary *gql_generated.RepoSummary
   144  			So(repoSummary, ShouldBeNil)
   145  
   146  			updateRepoSummaryVulnerabilities(ctx,
   147  				repoSummary,
   148  				SkipQGLField{
   149  					Vulnerabilities: false,
   150  				},
   151  				mocks.CveInfoMock{
   152  					GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string,
   153  					) (cvemodel.ImageCVESummary, error) {
   154  						return cvemodel.ImageCVESummary{
   155  							Count:       1,
   156  							MaxSeverity: "HIGH",
   157  						}, nil
   158  					},
   159  				},
   160  			)
   161  
   162  			So(repoSummary, ShouldBeNil)
   163  			So(graphql.GetErrors(ctx), ShouldBeNil)
   164  
   165  			imageSummary, _, err := ImageManifest2ImageSummary(ctx, GetFullImageMeta("0.1.0", repoMetaList[0],
   166  				imageMeta[image.DigestStr()]))
   167  			So(err, ShouldBeNil)
   168  
   169  			So(imageSummary, ShouldNotBeNil)
   170  
   171  			repoSummary = &gql_generated.RepoSummary{}
   172  			repoSummary.NewestImage = imageSummary
   173  
   174  			So(repoSummary.NewestImage.Vulnerabilities, ShouldBeNil)
   175  
   176  			updateImageSummaryVulnerabilities(ctx,
   177  				imageSummary,
   178  				SkipQGLField{
   179  					Vulnerabilities: false,
   180  				},
   181  				mocks.CveInfoMock{
   182  					GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string,
   183  					) (cvemodel.ImageCVESummary, error) {
   184  						return cvemodel.ImageCVESummary{
   185  							Count:       1,
   186  							MaxSeverity: "HIGH",
   187  						}, nil
   188  					},
   189  				},
   190  			)
   191  
   192  			So(repoSummary.NewestImage.Vulnerabilities, ShouldNotBeNil)
   193  			So(*repoSummary.NewestImage.Vulnerabilities.Count, ShouldEqual, 1)
   194  			So(*repoSummary.NewestImage.Vulnerabilities.MaxSeverity, ShouldEqual, "HIGH")
   195  			So(graphql.GetErrors(ctx), ShouldBeNil)
   196  		})
   197  
   198  		Convey("Add CVE Summary to ManifestSummary", func() {
   199  			var manifestSummary *gql_generated.ManifestSummary
   200  
   201  			So(manifestSummary, ShouldBeNil)
   202  
   203  			updateManifestSummaryVulnerabilities(ctx,
   204  				manifestSummary,
   205  				"repo1",
   206  				SkipQGLField{
   207  					Vulnerabilities: false,
   208  				},
   209  				mocks.CveInfoMock{
   210  					GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string,
   211  					) (cvemodel.ImageCVESummary, error) {
   212  						return cvemodel.ImageCVESummary{
   213  							Count:       1,
   214  							MaxSeverity: "HIGH",
   215  						}, nil
   216  					},
   217  				},
   218  			)
   219  
   220  			So(manifestSummary, ShouldBeNil)
   221  			So(graphql.GetErrors(ctx), ShouldBeNil)
   222  
   223  			imageSummary, _, err := ImageManifest2ImageSummary(ctx, GetFullImageMeta("0.1.0", repoMetaList[0],
   224  				imageMeta[image.DigestStr()]))
   225  			So(err, ShouldBeNil)
   226  			manifestSummary = imageSummary.Manifests[0]
   227  
   228  			updateManifestSummaryVulnerabilities(ctx,
   229  				manifestSummary,
   230  				"repo1",
   231  				SkipQGLField{
   232  					Vulnerabilities: true,
   233  				},
   234  				mocks.CveInfoMock{},
   235  			)
   236  
   237  			So(manifestSummary, ShouldNotBeNil)
   238  			So(manifestSummary.Vulnerabilities, ShouldNotBeNil)
   239  			So(*manifestSummary.Vulnerabilities.Count, ShouldEqual, 0)
   240  			So(*manifestSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "")
   241  
   242  			manifestSummary.Vulnerabilities = nil
   243  
   244  			updateManifestSummaryVulnerabilities(ctx,
   245  				manifestSummary,
   246  				"repo1",
   247  				SkipQGLField{
   248  					Vulnerabilities: false,
   249  				},
   250  				mocks.CveInfoMock{
   251  					GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string,
   252  					) (cvemodel.ImageCVESummary, error) {
   253  						return cvemodel.ImageCVESummary{
   254  							Count:       1,
   255  							MaxSeverity: "HIGH",
   256  						}, nil
   257  					},
   258  				},
   259  			)
   260  
   261  			So(manifestSummary.Vulnerabilities, ShouldNotBeNil)
   262  			So(*manifestSummary.Vulnerabilities.Count, ShouldEqual, 1)
   263  			So(*manifestSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "HIGH")
   264  
   265  			manifestSummary.Vulnerabilities = nil
   266  
   267  			updateManifestSummaryVulnerabilities(ctx,
   268  				manifestSummary,
   269  				"repo1",
   270  				SkipQGLField{
   271  					Vulnerabilities: false,
   272  				},
   273  				mocks.CveInfoMock{
   274  					GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string,
   275  					) (cvemodel.ImageCVESummary, error) {
   276  						return cvemodel.ImageCVESummary{}, ErrTestError
   277  					},
   278  				},
   279  			)
   280  
   281  			So(manifestSummary.Vulnerabilities, ShouldNotBeNil)
   282  			So(*manifestSummary.Vulnerabilities.Count, ShouldEqual, 0)
   283  			So(*manifestSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "")
   284  			So(graphql.GetErrors(ctx).Error(), ShouldContainSubstring, "unable to run vulnerability scan in repo")
   285  		})
   286  	})
   287  }