zotregistry.io/zot@v1.4.4-0.20231124084042-02a8ed785457/pkg/extensions/scrub/scrub_test.go (about) 1 //go:build scrub 2 // +build scrub 3 4 package scrub_test 5 6 import ( 7 "context" 8 "fmt" 9 "os" 10 "path" 11 "testing" 12 "time" 13 14 . "github.com/smartystreets/goconvey/convey" 15 16 "zotregistry.io/zot/pkg/api" 17 "zotregistry.io/zot/pkg/api/config" 18 extconf "zotregistry.io/zot/pkg/extensions/config" 19 "zotregistry.io/zot/pkg/extensions/monitoring" 20 "zotregistry.io/zot/pkg/extensions/scrub" 21 "zotregistry.io/zot/pkg/log" 22 "zotregistry.io/zot/pkg/storage" 23 "zotregistry.io/zot/pkg/storage/cache" 24 "zotregistry.io/zot/pkg/storage/local" 25 test "zotregistry.io/zot/pkg/test/common" 26 . "zotregistry.io/zot/pkg/test/image-utils" 27 ociutils "zotregistry.io/zot/pkg/test/oci-utils" 28 ) 29 30 const ( 31 repoName = "test" 32 ) 33 34 func TestScrubExtension(t *testing.T) { 35 Convey("Blobs integrity not affected", t, func(c C) { 36 port := test.GetFreePort() 37 38 logFile, err := os.CreateTemp("", "zot-log*.txt") 39 So(err, ShouldBeNil) 40 41 defer os.Remove(logFile.Name()) // clean up 42 43 conf := config.New() 44 conf.HTTP.Port = port 45 46 dir := t.TempDir() 47 subdir := t.TempDir() 48 49 conf.Storage.RootDirectory = dir 50 conf.Storage.Dedupe = false 51 conf.Storage.GC = false 52 53 substore := config.StorageConfig{RootDirectory: subdir} 54 conf.Storage.SubPaths = map[string]config.StorageConfig{"/a": substore} 55 conf.Log.Output = logFile.Name() 56 trueValue := true 57 scrubConfig := &extconf.ScrubConfig{ 58 BaseConfig: extconf.BaseConfig{Enable: &trueValue}, 59 Interval: 2, 60 } 61 conf.Extensions = &extconf.ExtensionConfig{ 62 Scrub: scrubConfig, 63 } 64 65 ctlr := api.NewController(conf) 66 67 srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", "")) 68 err = WriteImageToFileSystem(CreateDefaultVulnerableImage(), repoName, "0.0.1", srcStorageCtlr) 69 So(err, ShouldBeNil) 70 71 cm := test.NewControllerManager(ctlr) 72 cm.StartAndWait(port) 73 time.Sleep(6 * time.Second) 74 75 defer cm.StopServer() 76 77 data, err := os.ReadFile(logFile.Name()) 78 So(err, ShouldBeNil) 79 So(string(data), ShouldContainSubstring, "scrub: blobs/manifest ok") 80 }) 81 82 Convey("Blobs integrity affected", t, func(c C) { 83 port := test.GetFreePort() 84 85 logFile, err := os.CreateTemp("", "zot-log*.txt") 86 So(err, ShouldBeNil) 87 88 defer os.Remove(logFile.Name()) // clean up 89 90 conf := config.New() 91 conf.HTTP.Port = port 92 93 dir := t.TempDir() 94 95 conf.Storage.RootDirectory = dir 96 conf.Storage.Dedupe = false 97 conf.Storage.GC = false 98 99 conf.Log.Output = logFile.Name() 100 trueValue := true 101 scrubConfig := &extconf.ScrubConfig{ 102 BaseConfig: extconf.BaseConfig{Enable: &trueValue}, 103 Interval: 2, 104 } 105 conf.Extensions = &extconf.ExtensionConfig{ 106 Scrub: scrubConfig, 107 } 108 109 ctlr := api.NewController(conf) 110 111 srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", "")) 112 image := CreateDefaultVulnerableImage() 113 err = WriteImageToFileSystem(image, repoName, "0.0.1", srcStorageCtlr) 114 So(err, ShouldBeNil) 115 116 manifestDigest := image.ManifestDescriptor.Digest 117 118 err = os.Remove(path.Join(dir, repoName, "blobs/sha256", manifestDigest.Encoded())) 119 if err != nil { 120 panic(err) 121 } 122 123 cm := test.NewControllerManager(ctlr) 124 cm.StartAndWait(port) 125 time.Sleep(6 * time.Second) 126 127 defer cm.StopServer() 128 129 data, err := os.ReadFile(logFile.Name()) 130 So(err, ShouldBeNil) 131 So(string(data), ShouldContainSubstring, "scrub: blobs/manifest affected") 132 }) 133 134 Convey("Generator error - not enough permissions to access root directory", t, func(c C) { 135 port := test.GetFreePort() 136 137 logFile, err := os.CreateTemp("", "zot-log*.txt") 138 So(err, ShouldBeNil) 139 140 defer os.Remove(logFile.Name()) // clean up 141 142 conf := config.New() 143 conf.HTTP.Port = port 144 145 dir := t.TempDir() 146 147 conf.Storage.RootDirectory = dir 148 conf.Storage.Dedupe = false 149 conf.Storage.GC = false 150 151 conf.Log.Output = logFile.Name() 152 trueValue := true 153 scrubConfig := &extconf.ScrubConfig{ 154 BaseConfig: extconf.BaseConfig{Enable: &trueValue}, 155 Interval: 2, 156 } 157 conf.Extensions = &extconf.ExtensionConfig{ 158 Scrub: scrubConfig, 159 } 160 161 ctlr := api.NewController(conf) 162 163 srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", "")) 164 image := CreateDefaultVulnerableImage() 165 166 err = WriteImageToFileSystem(image, repoName, "0.0.1", srcStorageCtlr) 167 So(err, ShouldBeNil) 168 169 So(os.Chmod(path.Join(dir, repoName), 0o000), ShouldBeNil) 170 171 cm := test.NewControllerManager(ctlr) 172 cm.StartAndWait(port) 173 time.Sleep(6 * time.Second) 174 175 defer cm.StopServer() 176 177 data, err := os.ReadFile(logFile.Name()) 178 So(err, ShouldBeNil) 179 So(string(data), ShouldContainSubstring, "error while executing generator") 180 181 So(os.Chmod(path.Join(dir, repoName), 0o755), ShouldBeNil) 182 }) 183 } 184 185 func TestRunScrubRepo(t *testing.T) { 186 Convey("Blobs integrity not affected", t, func(c C) { 187 logFile, err := os.CreateTemp("", "zot-log*.txt") 188 So(err, ShouldBeNil) 189 190 defer os.Remove(logFile.Name()) // clean up 191 192 conf := config.New() 193 conf.Extensions = &extconf.ExtensionConfig{} 194 conf.Extensions.Lint = &extconf.LintConfig{} 195 196 dir := t.TempDir() 197 log := log.NewLogger("debug", logFile.Name()) 198 metrics := monitoring.NewMetricsServer(false, log) 199 cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{ 200 RootDir: dir, 201 Name: "cache", 202 UseRelPaths: true, 203 }, log) 204 imgStore := local.NewImageStore(dir, true, 205 true, log, metrics, nil, cacheDriver) 206 207 srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log) 208 image := CreateDefaultVulnerableImage() 209 210 err = WriteImageToFileSystem(image, repoName, "0.0.1", srcStorageCtlr) 211 So(err, ShouldBeNil) 212 213 err = scrub.RunScrubRepo(context.Background(), imgStore, repoName, log) 214 So(err, ShouldBeNil) 215 216 data, err := os.ReadFile(logFile.Name()) 217 So(err, ShouldBeNil) 218 So(string(data), ShouldContainSubstring, "scrub: blobs/manifest ok") 219 }) 220 221 Convey("Blobs integrity affected", t, func(c C) { 222 logFile, err := os.CreateTemp("", "zot-log*.txt") 223 So(err, ShouldBeNil) 224 225 defer os.Remove(logFile.Name()) // clean up 226 227 conf := config.New() 228 229 conf.Extensions = &extconf.ExtensionConfig{} 230 conf.Extensions.Lint = &extconf.LintConfig{} 231 232 dir := t.TempDir() 233 log := log.NewLogger("debug", logFile.Name()) 234 metrics := monitoring.NewMetricsServer(false, log) 235 cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{ 236 RootDir: dir, 237 Name: "cache", 238 UseRelPaths: true, 239 }, log) 240 imgStore := local.NewImageStore(dir, true, 241 true, log, metrics, nil, cacheDriver) 242 243 srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log) 244 image := CreateDefaultVulnerableImage() 245 246 err = WriteImageToFileSystem(image, repoName, "0.0.1", srcStorageCtlr) 247 So(err, ShouldBeNil) 248 249 manifestDigest := image.ManifestDescriptor.Digest 250 251 err = os.Remove(path.Join(dir, repoName, "blobs/sha256", manifestDigest.Encoded())) 252 if err != nil { 253 panic(err) 254 } 255 256 err = scrub.RunScrubRepo(context.Background(), imgStore, repoName, log) 257 So(err, ShouldBeNil) 258 259 data, err := os.ReadFile(logFile.Name()) 260 So(err, ShouldBeNil) 261 So(string(data), ShouldContainSubstring, "scrub: blobs/manifest affected") 262 }) 263 264 Convey("CheckRepo error - not enough permissions to access root directory", t, func(c C) { 265 logFile, err := os.CreateTemp("", "zot-log*.txt") 266 So(err, ShouldBeNil) 267 268 defer os.Remove(logFile.Name()) // clean up 269 270 conf := config.New() 271 conf.Extensions = &extconf.ExtensionConfig{} 272 conf.Extensions.Lint = &extconf.LintConfig{} 273 274 dir := t.TempDir() 275 log := log.NewLogger("debug", logFile.Name()) 276 metrics := monitoring.NewMetricsServer(false, log) 277 cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{ 278 RootDir: dir, 279 Name: "cache", 280 UseRelPaths: true, 281 }, log) 282 imgStore := local.NewImageStore(dir, true, true, log, metrics, nil, cacheDriver) 283 284 srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log) 285 image := CreateDefaultVulnerableImage() 286 287 err = WriteImageToFileSystem(image, repoName, "0.0.1", srcStorageCtlr) 288 So(err, ShouldBeNil) 289 290 So(os.Chmod(path.Join(dir, repoName), 0o000), ShouldBeNil) 291 292 err = scrub.RunScrubRepo(context.Background(), imgStore, repoName, log) 293 So(err, ShouldNotBeNil) 294 295 data, err := os.ReadFile(logFile.Name()) 296 So(err, ShouldBeNil) 297 So(string(data), ShouldContainSubstring, 298 fmt.Sprintf("error while running scrub for %s", imgStore.RootDir())) 299 So(os.Chmod(path.Join(dir, repoName), 0o755), ShouldBeNil) 300 }) 301 }