zotregistry.dev/zot@v1.4.4-0.20240314164342-eec277e14d20/pkg/extensions/lint/lint_test.go (about) 1 //go:build lint 2 // +build lint 3 4 package lint_test 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "net/http" 10 "os" 11 "path" 12 "testing" 13 14 godigest "github.com/opencontainers/go-digest" 15 ispec "github.com/opencontainers/image-spec/specs-go/v1" 16 . "github.com/smartystreets/goconvey/convey" 17 "gopkg.in/resty.v1" 18 19 "zotregistry.dev/zot/pkg/api" 20 "zotregistry.dev/zot/pkg/api/config" 21 extconf "zotregistry.dev/zot/pkg/extensions/config" 22 "zotregistry.dev/zot/pkg/extensions/lint" 23 "zotregistry.dev/zot/pkg/extensions/monitoring" 24 "zotregistry.dev/zot/pkg/log" 25 "zotregistry.dev/zot/pkg/storage/local" 26 test "zotregistry.dev/zot/pkg/test/common" 27 . "zotregistry.dev/zot/pkg/test/image-utils" 28 ociutils "zotregistry.dev/zot/pkg/test/oci-utils" 29 ) 30 31 func TestVerifyMandatoryAnnotations(t *testing.T) { 32 //nolint: dupl 33 Convey("Mandatory annotations disabled", t, func() { 34 port := test.GetFreePort() 35 baseURL := test.GetBaseURL(port) 36 37 conf := config.New() 38 conf.HTTP.Port = port 39 enable := false 40 conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}} 41 conf.Extensions.Lint.MandatoryAnnotations = []string{} 42 conf.Extensions.Lint.Enable = &enable 43 44 ctlr := api.NewController(conf) 45 dir := t.TempDir() 46 testStoreCtlr := ociutils.GetDefaultStoreController(dir, ctlr.Log) 47 48 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 49 So(err, ShouldBeNil) 50 51 ctlr.Config.Storage.RootDirectory = dir 52 53 cm := test.NewControllerManager(ctlr) 54 cm.StartAndWait(port) 55 defer cm.StopServer() 56 57 resp, err := resty.R().Get(baseURL + "/v2/zot-test/manifests/0.0.1") 58 So(err, ShouldBeNil) 59 So(resp, ShouldNotBeNil) 60 So(resp.StatusCode(), ShouldEqual, http.StatusOK) 61 62 manifestBlob := resp.Body() 63 var manifest ispec.Manifest 64 err = json.Unmarshal(manifestBlob, &manifest) 65 So(err, ShouldBeNil) 66 67 manifest.SchemaVersion = 2 68 content, err := json.Marshal(manifest) 69 So(err, ShouldBeNil) 70 71 resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json"). 72 SetBody(content).Put(baseURL + "/v2/zot-test/manifests/0.0.1") 73 So(err, ShouldBeNil) 74 So(resp.StatusCode(), ShouldEqual, http.StatusCreated) 75 }) 76 77 //nolint: dupl 78 Convey("Mandatory annotations enabled, but no list in config", t, func() { 79 port := test.GetFreePort() 80 baseURL := test.GetBaseURL(port) 81 82 conf := config.New() 83 conf.HTTP.Port = port 84 enable := true 85 conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}} 86 conf.Extensions.Lint.MandatoryAnnotations = []string{} 87 88 conf.Extensions.Lint.Enable = &enable 89 90 ctlr := api.NewController(conf) 91 dir := t.TempDir() 92 testStoreCtlr := ociutils.GetDefaultStoreController(dir, ctlr.Log) 93 94 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 95 So(err, ShouldBeNil) 96 97 ctlr.Config.Storage.RootDirectory = dir 98 99 cm := test.NewControllerManager(ctlr) 100 cm.StartAndWait(port) 101 defer cm.StopServer() 102 103 resp, err := resty.R().Get(baseURL + "/v2/zot-test/manifests/0.0.1") 104 So(err, ShouldBeNil) 105 So(resp, ShouldNotBeNil) 106 So(resp.StatusCode(), ShouldEqual, http.StatusOK) 107 108 manifestBlob := resp.Body() 109 var manifest ispec.Manifest 110 err = json.Unmarshal(manifestBlob, &manifest) 111 So(err, ShouldBeNil) 112 113 manifest.SchemaVersion = 2 114 content, err := json.Marshal(manifest) 115 So(err, ShouldBeNil) 116 117 resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json"). 118 SetBody(content).Put(baseURL + "/v2/zot-test/manifests/0.0.1") 119 So(err, ShouldBeNil) 120 So(resp.StatusCode(), ShouldEqual, http.StatusCreated) 121 }) 122 123 Convey("Mandatory annotations verification passing", t, func() { 124 port := test.GetFreePort() 125 baseURL := test.GetBaseURL(port) 126 127 conf := config.New() 128 conf.HTTP.Port = port 129 enable := true 130 conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}} 131 conf.Extensions.Lint.MandatoryAnnotations = []string{} 132 133 conf.Extensions.Lint.Enable = &enable 134 conf.Extensions.Lint.MandatoryAnnotations = []string{"annotation1", "annotation2", "annotation3"} 135 136 ctlr := api.NewController(conf) 137 dir := t.TempDir() 138 139 testStoreCtlr := ociutils.GetDefaultStoreController(dir, ctlr.Log) 140 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 141 So(err, ShouldBeNil) 142 143 ctlr.Config.Storage.RootDirectory = dir 144 145 cm := test.NewControllerManager(ctlr) 146 cm.StartAndWait(port) 147 defer cm.StopServer() 148 149 resp, err := resty.R().Get(baseURL + "/v2/zot-test/manifests/0.0.1") 150 So(err, ShouldBeNil) 151 So(resp, ShouldNotBeNil) 152 So(resp.StatusCode(), ShouldEqual, http.StatusOK) 153 154 manifestBlob := resp.Body() 155 var manifest ispec.Manifest 156 err = json.Unmarshal(manifestBlob, &manifest) 157 So(err, ShouldBeNil) 158 159 manifest.Annotations = make(map[string]string) 160 161 manifest.Annotations["annotation1"] = "testPass1" 162 manifest.Annotations["annotation2"] = "testPass2" 163 manifest.Annotations["annotation3"] = "testPass3" 164 165 manifest.SchemaVersion = 2 166 content, err := json.Marshal(manifest) 167 So(err, ShouldBeNil) 168 169 resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json"). 170 SetBody(content).Put(baseURL + "/v2/zot-test/manifests/0.0.1") 171 So(err, ShouldBeNil) 172 So(resp.StatusCode(), ShouldEqual, http.StatusCreated) 173 }) 174 175 Convey("Mandatory annotations verification in manifest and config passing", t, func() { 176 port := test.GetFreePort() 177 baseURL := test.GetBaseURL(port) 178 179 conf := config.New() 180 conf.HTTP.Port = port 181 enable := true 182 conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}} 183 conf.Extensions.Lint.MandatoryAnnotations = []string{} 184 185 conf.Extensions.Lint.Enable = &enable 186 conf.Extensions.Lint.MandatoryAnnotations = []string{"annotation1", "annotation2", "annotation3"} 187 188 ctlr := api.NewController(conf) 189 dir := t.TempDir() 190 191 testStoreCtlr := ociutils.GetDefaultStoreController(dir, ctlr.Log) 192 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 193 So(err, ShouldBeNil) 194 195 ctlr.Config.Storage.RootDirectory = dir 196 197 cm := test.NewControllerManager(ctlr) 198 cm.StartAndWait(port) 199 defer cm.StopServer() 200 201 resp, err := resty.R().Get(baseURL + "/v2/zot-test/manifests/0.0.1") 202 So(err, ShouldBeNil) 203 So(resp, ShouldNotBeNil) 204 So(resp.StatusCode(), ShouldEqual, http.StatusOK) 205 206 manifestBlob := resp.Body() 207 var manifest ispec.Manifest 208 err = json.Unmarshal(manifestBlob, &manifest) 209 So(err, ShouldBeNil) 210 211 manifest.Annotations = make(map[string]string) 212 213 manifest.Annotations["annotation1"] = "annotationPass1" 214 manifest.Annotations["annotation2"] = "annotationPass2" 215 216 configDigest := manifest.Config.Digest 217 218 resp, err = resty.R().Get(baseURL + fmt.Sprintf("/v2/zot-test/blobs/%s", configDigest)) 219 So(err, ShouldBeNil) 220 So(resp, ShouldNotBeNil) 221 So(resp.StatusCode(), ShouldEqual, http.StatusOK) 222 223 configBlob := resp.Body() 224 var imageConfig ispec.Image 225 err = json.Unmarshal(configBlob, &imageConfig) 226 So(err, ShouldBeNil) 227 228 imageConfig.Config.Labels = make(map[string]string) 229 imageConfig.Config.Labels["annotation3"] = "annotationPass3" 230 231 configContent, err := json.Marshal(imageConfig) 232 So(err, ShouldBeNil) 233 234 configBlobDigestRaw := godigest.FromBytes(configContent) 235 manifest.Config.Digest = configBlobDigestRaw 236 manifest.Config.Size = int64(len(configContent)) 237 manifestContent, err := json.Marshal(manifest) 238 So(err, ShouldBeNil) 239 240 // upload image config blob 241 resp, err = resty.R(). 242 Post(fmt.Sprintf("%s/v2/zot-test/blobs/uploads/", baseURL)) 243 So(err, ShouldBeNil) 244 loc := test.Location(baseURL, resp) 245 246 _, err = resty.R(). 247 SetContentLength(true). 248 SetHeader("Content-Length", fmt.Sprintf("%d", len(configContent))). 249 SetHeader("Content-Type", "application/octet-stream"). 250 SetQueryParam("digest", configBlobDigestRaw.String()). 251 SetBody(configContent). 252 Put(loc) 253 So(err, ShouldBeNil) 254 255 resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json"). 256 SetBody(manifestContent).Put(baseURL + "/v2/zot-test/manifests/0.0.1") 257 So(err, ShouldBeNil) 258 So(resp.StatusCode(), ShouldEqual, http.StatusCreated) 259 }) 260 261 Convey("Mandatory annotations verification in manifest and config failing", t, func() { 262 port := test.GetFreePort() 263 baseURL := test.GetBaseURL(port) 264 265 conf := config.New() 266 conf.HTTP.Port = port 267 enable := true 268 conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}} 269 conf.Extensions.Lint.MandatoryAnnotations = []string{} 270 271 conf.Extensions.Lint.Enable = &enable 272 conf.Extensions.Lint.MandatoryAnnotations = []string{"annotation1", "annotation2", "annotation3"} 273 274 ctlr := api.NewController(conf) 275 dir := t.TempDir() 276 277 testStoreCtlr := ociutils.GetDefaultStoreController(dir, ctlr.Log) 278 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 279 So(err, ShouldBeNil) 280 281 ctlr.Config.Storage.RootDirectory = dir 282 283 cm := test.NewControllerManager(ctlr) 284 cm.StartAndWait(port) 285 defer cm.StopServer() 286 287 resp, err := resty.R().Get(baseURL + "/v2/zot-test/manifests/0.0.1") 288 So(err, ShouldBeNil) 289 So(resp, ShouldNotBeNil) 290 So(resp.StatusCode(), ShouldEqual, http.StatusOK) 291 292 manifestBlob := resp.Body() 293 var manifest ispec.Manifest 294 err = json.Unmarshal(manifestBlob, &manifest) 295 So(err, ShouldBeNil) 296 297 manifest.Annotations = make(map[string]string) 298 299 manifest.Annotations["annotation1"] = "testFail1" 300 301 configDigest := manifest.Config.Digest 302 303 resp, err = resty.R().Get(baseURL + fmt.Sprintf("/v2/zot-test/blobs/%s", configDigest)) 304 So(err, ShouldBeNil) 305 So(resp, ShouldNotBeNil) 306 So(resp.StatusCode(), ShouldEqual, http.StatusOK) 307 308 configBlob := resp.Body() 309 var imageConfig ispec.Image 310 err = json.Unmarshal(configBlob, &imageConfig) 311 So(err, ShouldBeNil) 312 313 imageConfig.Config.Labels = make(map[string]string) 314 imageConfig.Config.Labels["annotation2"] = "testFail2" 315 316 configContent, err := json.Marshal(imageConfig) 317 So(err, ShouldBeNil) 318 319 configBlobDigestRaw := godigest.FromBytes(configContent) 320 manifest.Config.Digest = configBlobDigestRaw 321 manifest.Config.Size = int64(len(configContent)) 322 manifestContent, err := json.Marshal(manifest) 323 So(err, ShouldBeNil) 324 325 // upload image config blob 326 _, err = resty.R(). 327 Post(fmt.Sprintf("%s/v2/zot-test/blobs/uploads/", baseURL)) 328 So(err, ShouldBeNil) 329 loc := test.Location(baseURL, resp) 330 331 _, err = resty.R(). 332 SetContentLength(true). 333 SetHeader("Content-Length", fmt.Sprintf("%d", len(configContent))). 334 SetHeader("Content-Type", "application/octet-stream"). 335 SetQueryParam("digest", configBlobDigestRaw.String()). 336 SetBody(configContent). 337 Put(loc) 338 So(err, ShouldBeNil) 339 340 resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json"). 341 SetBody(manifestContent).Put(baseURL + "/v2/zot-test/manifests/0.0.1") 342 So(err, ShouldBeNil) 343 So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest) 344 }) 345 346 Convey("Mandatory annotations incomplete in manifest", t, func() { 347 port := test.GetFreePort() 348 baseURL := test.GetBaseURL(port) 349 350 conf := config.New() 351 conf.HTTP.Port = port 352 enable := true 353 conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}} 354 conf.Extensions.Lint.MandatoryAnnotations = []string{} 355 356 conf.Extensions.Lint.Enable = &enable 357 conf.Extensions.Lint.MandatoryAnnotations = []string{"annotation1", "annotation2", "annotation3"} 358 359 ctlr := api.NewController(conf) 360 dir := t.TempDir() 361 362 testStoreCtlr := ociutils.GetDefaultStoreController(dir, ctlr.Log) 363 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 364 So(err, ShouldBeNil) 365 366 ctlr.Config.Storage.RootDirectory = dir 367 368 cm := test.NewControllerManager(ctlr) 369 cm.StartAndWait(port) 370 defer cm.StopServer() 371 372 resp, err := resty.R().Get(baseURL + "/v2/zot-test/manifests/0.0.1") 373 So(err, ShouldBeNil) 374 So(resp, ShouldNotBeNil) 375 So(resp.StatusCode(), ShouldEqual, http.StatusOK) 376 377 manifestBlob := resp.Body() 378 var manifest ispec.Manifest 379 err = json.Unmarshal(manifestBlob, &manifest) 380 So(err, ShouldBeNil) 381 382 manifest.Annotations = make(map[string]string) 383 384 manifest.Annotations["annotation1"] = "testFail1" 385 manifest.Annotations["annotation3"] = "testFail3" 386 387 manifest.SchemaVersion = 2 388 content, err := json.Marshal(manifest) 389 So(err, ShouldBeNil) 390 391 resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json"). 392 SetBody(content).Put(baseURL + "/v2/zot-test/manifests/0.0.1") 393 So(err, ShouldBeNil) 394 So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest) 395 }) 396 397 Convey("Mandatory annotations verification passing - more annotations than the mandatory list", t, func() { 398 port := test.GetFreePort() 399 baseURL := test.GetBaseURL(port) 400 401 conf := config.New() 402 conf.HTTP.Port = port 403 enable := true 404 conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}} 405 conf.Extensions.Lint.MandatoryAnnotations = []string{} 406 conf.Extensions.Lint.Enable = &enable 407 conf.Extensions.Lint.MandatoryAnnotations = []string{"annotation1", "annotation2", "annotation3"} 408 409 ctlr := api.NewController(conf) 410 dir := t.TempDir() 411 412 testStoreCtlr := ociutils.GetDefaultStoreController(dir, ctlr.Log) 413 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 414 So(err, ShouldBeNil) 415 416 files, err := os.ReadDir(dir) 417 So(err, ShouldBeNil) 418 419 t.Log("Files in dir:", dir, ": ", files) 420 421 ctlr.Config.Storage.RootDirectory = dir 422 cm := test.NewControllerManager(ctlr) 423 424 cm.StartAndWait(port) 425 defer cm.StopServer() 426 427 resp, err := resty.R().Get(baseURL + "/v2/zot-test/manifests/0.0.1") 428 So(err, ShouldBeNil) 429 So(resp, ShouldNotBeNil) 430 So(resp.StatusCode(), ShouldEqual, http.StatusOK) 431 432 manifestBlob := resp.Body() 433 var manifest ispec.Manifest 434 err = json.Unmarshal(manifestBlob, &manifest) 435 So(err, ShouldBeNil) 436 437 manifest.Annotations = make(map[string]string) 438 439 manifest.Annotations["annotation1"] = "testPassMore1" 440 manifest.Annotations["annotation2"] = "testPassMore2" 441 manifest.Annotations["annotation3"] = "testPassMore3" 442 manifest.Annotations["annotation4"] = "testPassMore4" 443 444 manifest.SchemaVersion = 2 445 content, err := json.Marshal(manifest) 446 So(err, ShouldBeNil) 447 448 resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json"). 449 SetBody(content).Put(baseURL + "/v2/zot-test/manifests/0.0.1") 450 So(err, ShouldBeNil) 451 So(resp.StatusCode(), ShouldEqual, http.StatusCreated) 452 }) 453 } 454 455 func TestVerifyMandatoryAnnotationsFunction(t *testing.T) { 456 Convey("Mandatory annotations disabled", t, func() { 457 enable := false 458 459 lintConfig := &extconf.LintConfig{ 460 BaseConfig: extconf.BaseConfig{Enable: &enable}, 461 MandatoryAnnotations: []string{}, 462 } 463 464 dir := t.TempDir() 465 466 testStoreCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", "")) 467 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 468 So(err, ShouldBeNil) 469 470 var index ispec.Index 471 472 linter := lint.NewLinter(lintConfig, log.NewLogger("debug", "")) 473 imgStore := local.NewImageStore(dir, false, false, 474 log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil) 475 476 indexContent, err := imgStore.GetIndexContent("zot-test") 477 So(err, ShouldBeNil) 478 err = json.Unmarshal(indexContent, &index) 479 So(err, ShouldBeNil) 480 481 manifestDigest := index.Manifests[0].Digest 482 483 pass, err := linter.CheckMandatoryAnnotations("zot-test", manifestDigest, imgStore) 484 So(err, ShouldBeNil) 485 So(pass, ShouldBeTrue) 486 }) 487 488 Convey("Mandatory annotations enabled, but no list in config", t, func() { 489 enable := true 490 491 lintConfig := &extconf.LintConfig{ 492 BaseConfig: extconf.BaseConfig{Enable: &enable}, 493 MandatoryAnnotations: []string{}, 494 } 495 496 dir := t.TempDir() 497 498 testStoreCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", "")) 499 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 500 So(err, ShouldBeNil) 501 502 var index ispec.Index 503 504 linter := lint.NewLinter(lintConfig, log.NewLogger("debug", "")) 505 imgStore := local.NewImageStore(dir, false, false, 506 log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil) 507 508 indexContent, err := imgStore.GetIndexContent("zot-test") 509 So(err, ShouldBeNil) 510 err = json.Unmarshal(indexContent, &index) 511 So(err, ShouldBeNil) 512 513 manifestDigest := index.Manifests[0].Digest 514 515 pass, err := linter.CheckMandatoryAnnotations("zot-test", manifestDigest, imgStore) 516 So(err, ShouldBeNil) 517 So(pass, ShouldBeTrue) 518 }) 519 520 Convey("Mandatory annotations verification passing", t, func() { 521 enable := true 522 523 lintConfig := &extconf.LintConfig{ 524 BaseConfig: extconf.BaseConfig{Enable: &enable}, 525 MandatoryAnnotations: []string{"annotation1", "annotation2", "annotation3"}, 526 } 527 528 dir := t.TempDir() 529 530 testStoreCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", "")) 531 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 532 So(err, ShouldBeNil) 533 534 var index ispec.Index 535 buf, err := os.ReadFile(path.Join(dir, "zot-test", "index.json")) 536 So(err, ShouldBeNil) 537 err = json.Unmarshal(buf, &index) 538 So(err, ShouldBeNil) 539 540 manifestDigest := index.Manifests[0].Digest 541 542 var manifest ispec.Manifest 543 buf, err = os.ReadFile(path.Join(dir, "zot-test", "blobs", 544 manifestDigest.Algorithm().String(), manifestDigest.Encoded())) 545 So(err, ShouldBeNil) 546 err = json.Unmarshal(buf, &manifest) 547 So(err, ShouldBeNil) 548 549 manifest.Annotations = make(map[string]string) 550 551 manifest.Annotations["annotation1"] = "testPass1" 552 manifest.Annotations["annotation2"] = "testPass2" 553 manifest.Annotations["annotation3"] = "testPass3" 554 555 manifest.SchemaVersion = 2 556 content, err := json.Marshal(manifest) 557 So(err, ShouldBeNil) 558 So(content, ShouldNotBeNil) 559 560 digest := godigest.FromBytes(content) 561 So(digest, ShouldNotBeNil) 562 563 err = os.WriteFile(path.Join(dir, "zot-test", "blobs", 564 digest.Algorithm().String(), digest.Encoded()), content, 0o600) 565 So(err, ShouldBeNil) 566 567 manifestDesc := ispec.Descriptor{ 568 Size: int64(len(content)), 569 Digest: digest, 570 } 571 572 index.Manifests = append(index.Manifests, manifestDesc) 573 574 linter := lint.NewLinter(lintConfig, log.NewLogger("debug", "")) 575 imgStore := local.NewImageStore(dir, false, false, 576 log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil) 577 578 pass, err := linter.CheckMandatoryAnnotations("zot-test", digest, imgStore) 579 So(err, ShouldBeNil) 580 So(pass, ShouldBeTrue) 581 }) 582 583 Convey("Mandatory annotations incomplete in manifest", t, func() { 584 enable := true 585 586 lintConfig := &extconf.LintConfig{ 587 BaseConfig: extconf.BaseConfig{Enable: &enable}, 588 MandatoryAnnotations: []string{"annotation1", "annotation2", "annotation3"}, 589 } 590 591 dir := t.TempDir() 592 593 testStoreCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", "")) 594 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 595 So(err, ShouldBeNil) 596 597 var index ispec.Index 598 buf, err := os.ReadFile(path.Join(dir, "zot-test", "index.json")) 599 So(err, ShouldBeNil) 600 err = json.Unmarshal(buf, &index) 601 So(err, ShouldBeNil) 602 603 manifestDigest := index.Manifests[0].Digest 604 605 var manifest ispec.Manifest 606 buf, err = os.ReadFile(path.Join(dir, "zot-test", "blobs", 607 manifestDigest.Algorithm().String(), manifestDigest.Encoded())) 608 So(err, ShouldBeNil) 609 err = json.Unmarshal(buf, &manifest) 610 So(err, ShouldBeNil) 611 612 manifest.Annotations = make(map[string]string) 613 614 manifest.Annotations["annotation1"] = "test1" 615 manifest.Annotations["annotation3"] = "test3" 616 617 manifest.SchemaVersion = 2 618 content, err := json.Marshal(manifest) 619 So(err, ShouldBeNil) 620 So(content, ShouldNotBeNil) 621 622 digest := godigest.FromBytes(content) 623 So(digest, ShouldNotBeNil) 624 625 err = os.WriteFile(path.Join(dir, "zot-test", "blobs", 626 digest.Algorithm().String(), digest.Encoded()), content, 0o600) 627 So(err, ShouldBeNil) 628 629 manifestDesc := ispec.Descriptor{ 630 Size: int64(len(content)), 631 Digest: digest, 632 } 633 634 index.Manifests = append(index.Manifests, manifestDesc) 635 636 linter := lint.NewLinter(lintConfig, log.NewLogger("debug", "")) 637 imgStore := local.NewImageStore(dir, false, false, 638 log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil) 639 640 pass, err := linter.CheckMandatoryAnnotations("zot-test", digest, imgStore) 641 So(err, ShouldNotBeNil) 642 So(pass, ShouldBeFalse) 643 }) 644 645 Convey("Mandatory annotations verification passing - more annotations than the mandatory list", t, func() { 646 enable := true 647 648 lintConfig := &extconf.LintConfig{ 649 BaseConfig: extconf.BaseConfig{Enable: &enable}, 650 MandatoryAnnotations: []string{"annotation1", "annotation2", "annotation3"}, 651 } 652 653 dir := t.TempDir() 654 655 testStoreCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", "")) 656 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 657 So(err, ShouldBeNil) 658 659 var index ispec.Index 660 buf, err := os.ReadFile(path.Join(dir, "zot-test", "index.json")) 661 So(err, ShouldBeNil) 662 err = json.Unmarshal(buf, &index) 663 So(err, ShouldBeNil) 664 665 manifestDigest := index.Manifests[0].Digest 666 667 var manifest ispec.Manifest 668 buf, err = os.ReadFile(path.Join(dir, "zot-test", "blobs", 669 manifestDigest.Algorithm().String(), manifestDigest.Encoded())) 670 So(err, ShouldBeNil) 671 err = json.Unmarshal(buf, &manifest) 672 So(err, ShouldBeNil) 673 674 manifest.Annotations = make(map[string]string) 675 676 manifest.Annotations["annotation1"] = "testPassMore1" 677 manifest.Annotations["annotation2"] = "testPassMore2" 678 manifest.Annotations["annotation3"] = "testPassMore3" 679 manifest.Annotations["annotation4"] = "testPassMore4" 680 681 manifest.SchemaVersion = 2 682 content, err := json.Marshal(manifest) 683 So(err, ShouldBeNil) 684 So(content, ShouldNotBeNil) 685 686 digest := godigest.FromBytes(content) 687 So(digest, ShouldNotBeNil) 688 689 err = os.WriteFile(path.Join(dir, "zot-test", "blobs", 690 digest.Algorithm().String(), digest.Encoded()), content, 0o600) 691 So(err, ShouldBeNil) 692 693 manifestDesc := ispec.Descriptor{ 694 Size: int64(len(content)), 695 Digest: digest, 696 } 697 698 index.Manifests = append(index.Manifests, manifestDesc) 699 700 linter := lint.NewLinter(lintConfig, log.NewLogger("debug", "")) 701 imgStore := local.NewImageStore(dir, false, false, 702 log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil) 703 704 pass, err := linter.CheckMandatoryAnnotations("zot-test", digest, imgStore) 705 So(err, ShouldBeNil) 706 So(pass, ShouldBeTrue) 707 }) 708 709 Convey("Cannot unmarshal manifest", t, func() { 710 enable := true 711 712 lintConfig := &extconf.LintConfig{ 713 BaseConfig: extconf.BaseConfig{Enable: &enable}, 714 MandatoryAnnotations: []string{"annotation1", "annotation2", "annotation3"}, 715 } 716 717 dir := t.TempDir() 718 719 testStoreCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", "")) 720 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 721 So(err, ShouldBeNil) 722 723 var index ispec.Index 724 buf, err := os.ReadFile(path.Join(dir, "zot-test", "index.json")) 725 So(err, ShouldBeNil) 726 err = json.Unmarshal(buf, &index) 727 So(err, ShouldBeNil) 728 729 manifestDigest := index.Manifests[0].Digest 730 731 var manifest ispec.Manifest 732 buf, err = os.ReadFile(path.Join(dir, "zot-test", "blobs", 733 manifestDigest.Algorithm().String(), manifestDigest.Encoded())) 734 So(err, ShouldBeNil) 735 err = json.Unmarshal(buf, &manifest) 736 So(err, ShouldBeNil) 737 738 manifest.Annotations = make(map[string]string) 739 740 manifest.Annotations["annotation1"] = "testUnmarshal1" 741 manifest.Annotations["annotation2"] = "testUnmarshal2" 742 manifest.Annotations["annotation3"] = "testUnmarshal3" 743 744 manifest.SchemaVersion = 2 745 content, err := json.Marshal(manifest) 746 So(err, ShouldBeNil) 747 So(content, ShouldNotBeNil) 748 749 digest := godigest.FromBytes(content) 750 So(digest, ShouldNotBeNil) 751 752 err = os.WriteFile(path.Join(dir, "zot-test", "blobs", 753 digest.Algorithm().String(), digest.Encoded()), content, 0o600) 754 So(err, ShouldBeNil) 755 756 manifestDesc := ispec.Descriptor{ 757 Size: int64(len(content)), 758 Digest: digest, 759 } 760 761 index.Manifests = append(index.Manifests, manifestDesc) 762 763 linter := lint.NewLinter(lintConfig, log.NewLogger("debug", "")) 764 imgStore := local.NewImageStore(dir, false, false, 765 log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil) 766 767 err = os.Chmod(path.Join(dir, "zot-test", "blobs"), 0o000) 768 if err != nil { 769 panic(err) 770 } 771 772 pass, err := linter.CheckMandatoryAnnotations("zot-test", digest, imgStore) 773 So(err, ShouldNotBeNil) 774 So(pass, ShouldBeFalse) 775 776 err = os.Chmod(path.Join(dir, "zot-test", "blobs"), 0o755) 777 if err != nil { 778 panic(err) 779 } 780 }) 781 782 Convey("Cannot get config file", t, func() { 783 enable := true 784 785 lintConfig := &extconf.LintConfig{ 786 BaseConfig: extconf.BaseConfig{Enable: &enable}, 787 MandatoryAnnotations: []string{"annotation1", "annotation2", "annotation3"}, 788 } 789 790 dir := t.TempDir() 791 792 testStoreCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", "")) 793 err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr) 794 So(err, ShouldBeNil) 795 796 var index ispec.Index 797 buf, err := os.ReadFile(path.Join(dir, "zot-test", "index.json")) 798 So(err, ShouldBeNil) 799 err = json.Unmarshal(buf, &index) 800 So(err, ShouldBeNil) 801 802 manifestDigest := index.Manifests[0].Digest 803 804 var manifest ispec.Manifest 805 buf, err = os.ReadFile(path.Join(dir, "zot-test", "blobs", 806 manifestDigest.Algorithm().String(), manifestDigest.Encoded())) 807 So(err, ShouldBeNil) 808 err = json.Unmarshal(buf, &manifest) 809 So(err, ShouldBeNil) 810 811 manifest.Annotations = make(map[string]string) 812 813 manifest.Annotations["annotation1"] = "testAnnotation1" 814 manifest.Annotations["annotation2"] = "testAnnotation2" 815 816 // write config 817 var imageConfig ispec.Image 818 configDigest := manifest.Config.Digest 819 buf, err = os.ReadFile(path.Join(dir, "zot-test", "blobs", "sha256", 820 configDigest.Encoded())) 821 So(err, ShouldBeNil) 822 err = json.Unmarshal(buf, &imageConfig) 823 So(err, ShouldBeNil) 824 825 imageConfig.Config.Labels = make(map[string]string) 826 imageConfig.Config.Labels["annotation3"] = "testAnnotation3" 827 828 configContent, err := json.Marshal(imageConfig) 829 So(err, ShouldBeNil) 830 So(configContent, ShouldNotBeNil) 831 832 cfgDigest := godigest.FromBytes(configContent) 833 So(cfgDigest, ShouldNotBeNil) 834 835 err = os.WriteFile(path.Join(dir, "zot-test", "blobs", "sha256", 836 cfgDigest.Encoded()), configContent, 0o600) 837 So(err, ShouldBeNil) 838 839 // write manifest 840 manifest.SchemaVersion = 2 841 manifest.Config.Size = int64(len(configContent)) 842 manifest.Config.Digest = cfgDigest 843 manifestContent, err := json.Marshal(manifest) 844 So(err, ShouldBeNil) 845 So(manifestContent, ShouldNotBeNil) 846 847 digest := godigest.FromBytes(manifestContent) 848 So(digest, ShouldNotBeNil) 849 850 err = os.WriteFile(path.Join(dir, "zot-test", "blobs", 851 digest.Algorithm().String(), digest.Encoded()), manifestContent, 0o600) 852 So(err, ShouldBeNil) 853 854 manifestDesc := ispec.Descriptor{ 855 Size: int64(len(manifestContent)), 856 Digest: digest, 857 } 858 859 index.Manifests = append(index.Manifests, manifestDesc) 860 861 linter := lint.NewLinter(lintConfig, log.NewLogger("debug", "")) 862 imgStore := local.NewImageStore(dir, false, false, 863 log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil) 864 865 err = os.Chmod(path.Join(dir, "zot-test", "blobs", "sha256", manifest.Config.Digest.Encoded()), 0o000) 866 if err != nil { 867 panic(err) 868 } 869 870 pass, err := linter.CheckMandatoryAnnotations("zot-test", digest, imgStore) 871 So(err, ShouldNotBeNil) 872 So(pass, ShouldBeFalse) 873 874 err = os.Chmod(path.Join(dir, "zot-test", "blobs", "sha256", manifest.Config.Digest.Encoded()), 0o755) 875 if err != nil { 876 panic(err) 877 } 878 879 pass, err = linter.CheckMandatoryAnnotations("zot-test", digest, imgStore) 880 So(err, ShouldBeNil) 881 So(pass, ShouldBeTrue) 882 }) 883 }