zotregistry.dev/zot@v1.4.4-0.20240314164342-eec277e14d20/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.dev/zot/pkg/extensions/search/cve/model" 15 "zotregistry.dev/zot/pkg/extensions/search/gql_generated" 16 "zotregistry.dev/zot/pkg/log" 17 "zotregistry.dev/zot/pkg/meta/boltdb" 18 . "zotregistry.dev/zot/pkg/test/image-utils" 19 "zotregistry.dev/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.UnknownCount, ShouldEqual, 0) 92 So(*imageSummary.Vulnerabilities.LowCount, ShouldEqual, 0) 93 So(*imageSummary.Vulnerabilities.MediumCount, ShouldEqual, 0) 94 So(*imageSummary.Vulnerabilities.HighCount, ShouldEqual, 0) 95 So(*imageSummary.Vulnerabilities.CriticalCount, ShouldEqual, 0) 96 So(*imageSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "") 97 So(graphql.GetErrors(ctx), ShouldBeNil) 98 99 imageSummary.Vulnerabilities = nil 100 101 updateImageSummaryVulnerabilities(ctx, 102 imageSummary, 103 SkipQGLField{ 104 Vulnerabilities: false, 105 }, 106 mocks.CveInfoMock{ 107 GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string, 108 ) (cvemodel.ImageCVESummary, error) { 109 return cvemodel.ImageCVESummary{ 110 Count: 30, 111 UnknownCount: 1, 112 LowCount: 2, 113 MediumCount: 3, 114 HighCount: 10, 115 CriticalCount: 14, 116 MaxSeverity: "HIGH", 117 }, nil 118 }, 119 }, 120 ) 121 122 So(imageSummary.Vulnerabilities, ShouldNotBeNil) 123 So(*imageSummary.Vulnerabilities.Count, ShouldEqual, 30) 124 So(*imageSummary.Vulnerabilities.UnknownCount, ShouldEqual, 1) 125 So(*imageSummary.Vulnerabilities.LowCount, ShouldEqual, 2) 126 So(*imageSummary.Vulnerabilities.MediumCount, ShouldEqual, 3) 127 So(*imageSummary.Vulnerabilities.HighCount, ShouldEqual, 10) 128 So(*imageSummary.Vulnerabilities.CriticalCount, ShouldEqual, 14) 129 So(*imageSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "HIGH") 130 So(graphql.GetErrors(ctx), ShouldBeNil) 131 So(len(imageSummary.Manifests), ShouldEqual, 1) 132 So(imageSummary.Manifests[0].Vulnerabilities, ShouldNotBeNil) 133 So(*imageSummary.Manifests[0].Vulnerabilities.Count, ShouldEqual, 30) 134 So(*imageSummary.Manifests[0].Vulnerabilities.UnknownCount, ShouldEqual, 1) 135 So(*imageSummary.Manifests[0].Vulnerabilities.LowCount, ShouldEqual, 2) 136 So(*imageSummary.Manifests[0].Vulnerabilities.MediumCount, ShouldEqual, 3) 137 So(*imageSummary.Manifests[0].Vulnerabilities.HighCount, ShouldEqual, 10) 138 So(*imageSummary.Manifests[0].Vulnerabilities.CriticalCount, ShouldEqual, 14) 139 So(*imageSummary.Manifests[0].Vulnerabilities.MaxSeverity, ShouldEqual, "HIGH") 140 141 imageSummary.Vulnerabilities = nil 142 143 updateImageSummaryVulnerabilities(ctx, 144 imageSummary, 145 SkipQGLField{ 146 Vulnerabilities: false, 147 }, 148 mocks.CveInfoMock{ 149 GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string, 150 ) (cvemodel.ImageCVESummary, error) { 151 return cvemodel.ImageCVESummary{}, ErrTestError 152 }, 153 }, 154 ) 155 156 So(imageSummary.Vulnerabilities, ShouldNotBeNil) 157 So(*imageSummary.Vulnerabilities.Count, ShouldEqual, 0) 158 So(*imageSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "") 159 So(graphql.GetErrors(ctx).Error(), ShouldContainSubstring, "unable to run vulnerability scan on tag") 160 }) 161 162 Convey("Add CVE Summary to RepoSummary", func() { 163 var repoSummary *gql_generated.RepoSummary 164 So(repoSummary, ShouldBeNil) 165 166 updateRepoSummaryVulnerabilities(ctx, 167 repoSummary, 168 SkipQGLField{ 169 Vulnerabilities: false, 170 }, 171 mocks.CveInfoMock{ 172 GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string, 173 ) (cvemodel.ImageCVESummary, error) { 174 return cvemodel.ImageCVESummary{ 175 Count: 30, 176 UnknownCount: 1, 177 LowCount: 2, 178 MediumCount: 3, 179 HighCount: 10, 180 CriticalCount: 14, 181 MaxSeverity: "HIGH", 182 }, nil 183 }, 184 }, 185 ) 186 187 So(repoSummary, ShouldBeNil) 188 So(graphql.GetErrors(ctx), ShouldBeNil) 189 190 imageSummary, _, err := ImageManifest2ImageSummary(ctx, GetFullImageMeta("0.1.0", repoMetaList[0], 191 imageMeta[image.DigestStr()])) 192 So(err, ShouldBeNil) 193 194 So(imageSummary, ShouldNotBeNil) 195 196 repoSummary = &gql_generated.RepoSummary{} 197 repoSummary.NewestImage = imageSummary 198 199 So(repoSummary.NewestImage.Vulnerabilities, ShouldBeNil) 200 201 updateImageSummaryVulnerabilities(ctx, 202 imageSummary, 203 SkipQGLField{ 204 Vulnerabilities: false, 205 }, 206 mocks.CveInfoMock{ 207 GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string, 208 ) (cvemodel.ImageCVESummary, error) { 209 return cvemodel.ImageCVESummary{ 210 Count: 30, 211 UnknownCount: 1, 212 LowCount: 2, 213 MediumCount: 3, 214 HighCount: 10, 215 CriticalCount: 14, 216 MaxSeverity: "HIGH", 217 }, nil 218 }, 219 }, 220 ) 221 222 So(repoSummary.NewestImage.Vulnerabilities, ShouldNotBeNil) 223 So(*repoSummary.NewestImage.Vulnerabilities.Count, ShouldEqual, 30) 224 So(*repoSummary.NewestImage.Vulnerabilities.UnknownCount, ShouldEqual, 1) 225 So(*repoSummary.NewestImage.Vulnerabilities.LowCount, ShouldEqual, 2) 226 So(*repoSummary.NewestImage.Vulnerabilities.MediumCount, ShouldEqual, 3) 227 So(*repoSummary.NewestImage.Vulnerabilities.HighCount, ShouldEqual, 10) 228 So(*repoSummary.NewestImage.Vulnerabilities.CriticalCount, ShouldEqual, 14) 229 So(*repoSummary.NewestImage.Vulnerabilities.MaxSeverity, ShouldEqual, "HIGH") 230 So(graphql.GetErrors(ctx), ShouldBeNil) 231 }) 232 233 Convey("Add CVE Summary to ManifestSummary", func() { 234 var manifestSummary *gql_generated.ManifestSummary 235 236 So(manifestSummary, ShouldBeNil) 237 238 updateManifestSummaryVulnerabilities(ctx, 239 manifestSummary, 240 "repo1", 241 SkipQGLField{ 242 Vulnerabilities: false, 243 }, 244 mocks.CveInfoMock{ 245 GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string, 246 ) (cvemodel.ImageCVESummary, error) { 247 return cvemodel.ImageCVESummary{ 248 Count: 1, 249 MaxSeverity: "HIGH", 250 }, nil 251 }, 252 }, 253 ) 254 255 So(manifestSummary, ShouldBeNil) 256 So(graphql.GetErrors(ctx), ShouldBeNil) 257 258 imageSummary, _, err := ImageManifest2ImageSummary(ctx, GetFullImageMeta("0.1.0", repoMetaList[0], 259 imageMeta[image.DigestStr()])) 260 So(err, ShouldBeNil) 261 manifestSummary = imageSummary.Manifests[0] 262 263 updateManifestSummaryVulnerabilities(ctx, 264 manifestSummary, 265 "repo1", 266 SkipQGLField{ 267 Vulnerabilities: true, 268 }, 269 mocks.CveInfoMock{}, 270 ) 271 272 So(manifestSummary, ShouldNotBeNil) 273 So(manifestSummary.Vulnerabilities, ShouldNotBeNil) 274 So(*manifestSummary.Vulnerabilities.Count, ShouldEqual, 0) 275 So(*manifestSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "") 276 277 manifestSummary.Vulnerabilities = nil 278 279 updateManifestSummaryVulnerabilities(ctx, 280 manifestSummary, 281 "repo1", 282 SkipQGLField{ 283 Vulnerabilities: false, 284 }, 285 mocks.CveInfoMock{ 286 GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string, 287 ) (cvemodel.ImageCVESummary, error) { 288 return cvemodel.ImageCVESummary{ 289 Count: 30, 290 UnknownCount: 1, 291 LowCount: 2, 292 MediumCount: 3, 293 HighCount: 10, 294 CriticalCount: 14, 295 MaxSeverity: "HIGH", 296 }, nil 297 }, 298 }, 299 ) 300 301 So(manifestSummary.Vulnerabilities, ShouldNotBeNil) 302 So(*manifestSummary.Vulnerabilities.Count, ShouldEqual, 30) 303 So(*manifestSummary.Vulnerabilities.UnknownCount, ShouldEqual, 1) 304 So(*manifestSummary.Vulnerabilities.LowCount, ShouldEqual, 2) 305 So(*manifestSummary.Vulnerabilities.MediumCount, ShouldEqual, 3) 306 So(*manifestSummary.Vulnerabilities.HighCount, ShouldEqual, 10) 307 So(*manifestSummary.Vulnerabilities.CriticalCount, ShouldEqual, 14) 308 So(*manifestSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "HIGH") 309 310 manifestSummary.Vulnerabilities = nil 311 312 updateManifestSummaryVulnerabilities(ctx, 313 manifestSummary, 314 "repo1", 315 SkipQGLField{ 316 Vulnerabilities: false, 317 }, 318 mocks.CveInfoMock{ 319 GetCVESummaryForImageMediaFn: func(ctx context.Context, repo string, digest, mediaType string, 320 ) (cvemodel.ImageCVESummary, error) { 321 return cvemodel.ImageCVESummary{}, ErrTestError 322 }, 323 }, 324 ) 325 326 So(manifestSummary.Vulnerabilities, ShouldNotBeNil) 327 So(*manifestSummary.Vulnerabilities.Count, ShouldEqual, 0) 328 So(*manifestSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "") 329 So(graphql.GetErrors(ctx).Error(), ShouldContainSubstring, "unable to run vulnerability scan in repo") 330 }) 331 }) 332 }