diff --git a/errors/errors.go b/errors/errors.go index 5bcca71e..ed2dcf42 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -50,6 +50,7 @@ var ( ErrCliBadConfig = errors.New("cli: bad config") ErrRepoNotFound = errors.New("repository: not found") ErrRepoBadVersion = errors.New("repository: unsupported layout version") + ErrRepoBadLayout = errors.New("repository: invalid layout") ErrManifestNotFound = errors.New("manifest: not found") ErrBadManifest = errors.New("manifest: invalid contents") ErrUploadNotFound = errors.New("uploads: not found") diff --git a/go.mod b/go.mod index 3bbe0c34..402d1531 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ go 1.20 require ( github.com/99designs/gqlgen v0.17.38 github.com/Masterminds/semver v1.5.0 - github.com/apex/log v1.9.0 // indirect github.com/aquasecurity/trivy-db v0.0.0-20230831170347-f732860d4917 github.com/bmatcuk/doublestar/v4 v4.6.0 github.com/briandowns/spinner v1.23.0 @@ -27,7 +26,6 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0-rc5 - github.com/opencontainers/umoci v0.4.8-0.20210922062158-e60a0cc726e6 github.com/oras-project/artifacts-spec v1.0.0-rc.2 github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 github.com/prometheus/client_golang v1.16.0 @@ -439,7 +437,6 @@ require ( github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/rootless-containers/proto/go-proto v0.0.0-20210921234734-69430b6543fb // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/saracen/walker v0.1.3 // indirect github.com/sassoftware/relic v7.2.1+incompatible // indirect @@ -471,8 +468,6 @@ require ( github.com/transparency-dev/merkle v0.0.2 // indirect github.com/twitchtv/twirp v8.1.2+incompatible // indirect github.com/ulikunitz/xz v0.5.11 // indirect - github.com/urfave/cli v1.22.14 // indirect - github.com/vbatts/go-mtree v0.5.2 // indirect github.com/vbatts/tar-split v0.11.5 // indirect github.com/xanzy/go-gitlab v0.90.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect diff --git a/go.sum b/go.sum index ec0d9196..62d5bd4e 100644 --- a/go.sum +++ b/go.sum @@ -197,7 +197,6 @@ filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= github.com/99designs/gqlgen v0.17.38 h1:3r7G7i8UAdY0iYreNiBAA55auVsrowO0+ZhMl5g4GYU= github.com/99designs/gqlgen v0.17.38/go.mod h1:2v+dKtpI8mIzYeW9dYN8mO69tMmjszW2xKLNcWR/5wQ= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20210401092550-0a8691dafd0d/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA= @@ -374,11 +373,6 @@ github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apex/log v1.9.0 h1:FHtw/xuaM8AgmvDDTI9fiwoAL25Sq2cxojnZICUU8l0= -github.com/apex/log v1.9.0/go.mod h1:m82fZlWIuiWzWP04XCTXmnX0xRkYYbCdYn8jbJeLBEA= -github.com/apex/logs v1.0.0/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= -github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= -github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= @@ -419,7 +413,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.44.287/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go v1.45.15 h1:gYBTVSYuhXdatrLbsPaRgVcc637zzdgThWmsDRwXLOo= @@ -501,7 +494,6 @@ github.com/aws/smithy-go v1.14.2 h1:MJU9hqBGbvWZdApzpvoF2WAIJDbtjK2NDJSiJP7HblQ= github.com/aws/smithy-go v1.14.2/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20220228164355-396b2034c795 h1:IWeCJzU+IYaO2rVEBlGPTBfe90cmGXFTLdhUFlzDGsY= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20220228164355-396b2034c795/go.mod h1:8vJsEZ4iRqG+Vx6pKhWK6U00qcj0KC37IsfszMkY6UE= -github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -510,7 +502,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= @@ -546,7 +537,6 @@ github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNS github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/chartmuseum/auth v0.5.0 h1:ENNmoxvjxcR/JR0HrghAEtGQe7hToMNj16+UoS5CK9Y= github.com/chartmuseum/auth v0.5.0/go.mod h1:BvoSXHyvbsq+/bbhNgVTDQsModM+HERBTNY5o9Vyrig= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/cheggaaa/pb/v3 v3.1.4 h1:DN8j4TVVdKu3WxVwcRKu0sG00IIU6FewoABZzXbRQeo= github.com/cheggaaa/pb/v3 v3.1.4/go.mod h1:6wVjILNBaXMs8c21qRiaUM8BR82erfgau1DQ4iUXmSA= @@ -555,7 +545,6 @@ github.com/chrismellard/docker-credential-acr-env v0.0.0-20220119192733-fe33c00c github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/clbanning/mxj/v2 v2.5.6 h1:Jm4VaCI/+Ug5Q57IzEoZbwx4iQFA6wkXv72juUSeK+g= github.com/clbanning/mxj/v2 v2.5.6/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -579,7 +568,6 @@ github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/containerd v1.7.6 h1:oNAVsnhPoy4BTPQivLgTzI9Oleml9l/+eYIDYXRCYo8= github.com/containerd/containerd v1.7.6/go.mod h1:SY6lrkkuJT40BVNO37tlYTSnKJnP5AXBc0fhx0q+TJ4= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= @@ -623,8 +611,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/cyberphone/json-canonicalization v0.0.0-20230710064741-aa7fe85c7dbd h1:0av0vtcjA8Hqv5gyWj79CLCFVwOOyBNWPjrfUWceMNg= github.com/cyberphone/json-canonicalization v0.0.0-20230710064741-aa7fe85c7dbd/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= -github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/danieljoos/wincred v1.2.0 h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE= @@ -675,7 +661,6 @@ github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= @@ -720,7 +705,6 @@ github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/flynn/go-docopt v0.0.0-20140912013429-f6dd2ebbb31e/go.mod h1:HyVoz1Mz5Co8TFO8EupIdlcpwShBmY98dkT2xeHkvEI= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -1124,7 +1108,6 @@ github.com/jedisct1/go-minisign v0.0.0-20211028175153-1c139d1cc84b h1:ZGiXF8sz7P github.com/jedisct1/go-minisign v0.0.0-20211028175153-1c139d1cc84b/go.mod h1:hQmNrgofl+IY/8L+n20H6E6PWBBTokdsv+q49j0QhsU= github.com/jellydator/ttlcache/v3 v3.0.1 h1:cHgCSMS7TdQcoprXnWUptJZzyFsqs18Lt8VVhRuZYVU= github.com/jeremija/gosubmit v0.2.7 h1:At0OhGCFGPXyjPYAsCchoBUhE099pcBXmsb4iZqROIc= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -1136,7 +1119,6 @@ github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqx github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -1159,12 +1141,10 @@ github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f h1:GvCU5GXhHq+7LeOzx/haG7HSIZokl3/0GkoUFzsRJjg= @@ -1183,7 +1163,6 @@ github.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uF github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -1262,16 +1241,12 @@ github.com/masahiro331/go-xfs-filesystem v0.0.0-20230608043311-a335f4599b70/go.m github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= @@ -1292,7 +1267,6 @@ github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/microsoft/go-rustaudit v0.0.0-20220808201409-204dfee52032 h1:TLygBUBxikNJJfLwgm+Qwdgq1FtfV8Uh7bcxRyTzK8s= github.com/microsoft/go-rustaudit v0.0.0-20220808201409-204dfee52032/go.mod h1:vYT9HE7WCvL64iVeZylKmCsWKfE+JZ8105iuh2Trk8g= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -1334,7 +1308,6 @@ github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= @@ -1350,8 +1323,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= @@ -1361,7 +1332,6 @@ github.com/mozillazg/docker-credential-acr-helper v0.3.0 h1:DVWFZ3/O8BP6Ue3iS/Ol github.com/mozillazg/docker-credential-acr-helper v0.3.0/go.mod h1:cZlu3tof523ujmLuiNUb6JsjtHcNA70u1jitrrdnuyA= github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de h1:D5x39vF5KCwKQaw+OC9ZPiLVHXz3UFw2+psEX+gYcto= github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de/go.mod h1:kJun4WP5gFuHZgRjZUWWuH1DTxCtxbHDOIJsudS8jzY= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -1396,7 +1366,6 @@ github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042 github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= @@ -1409,20 +1378,14 @@ github.com/opencontainers/distribution-spec/specs-go v0.0.0-20230117141039-067a0 github.com/opencontainers/distribution-spec/specs-go v0.0.0-20230117141039-067a0f5b0e25/go.mod h1:uLvbyisMXc6uWXBmKrPegq9igec91coS/kGM2sHL660= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM= github.com/opencontainers/runc v1.1.9/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= -github.com/opencontainers/umoci v0.4.8-0.20210922062158-e60a0cc726e6 h1:yRmw/21YcR/78dRoFyWNJ6c3VxOXqe97PhNZI0Ib7bM= -github.com/opencontainers/umoci v0.4.8-0.20210922062158-e60a0cc726e6/go.mod h1:kO0Bh4G4BZUh2QSlqsCR/OCtdqLjmt3mvD6okZhMBlU= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openvex/go-vex v0.2.5 h1:41utdp2rHgAGCsG+UbjmfMG5CWQxs15nGqir1eRgSrQ= @@ -1514,7 +1477,6 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1523,8 +1485,6 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rootless-containers/proto/go-proto v0.0.0-20210921234734-69430b6543fb h1:nkbcM8VoyGDolfdJKoIZc9QSlJrm3IrCg/0/v7VhK/0= -github.com/rootless-containers/proto/go-proto v0.0.0-20210921234734-69430b6543fb/go.mod h1:LLjEAc6zmycfeN7/1fxIphWQPjHpTt7ElqT7eVf8e4A= github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= @@ -1545,7 +1505,6 @@ github.com/sassoftware/relic v7.2.1+incompatible h1:Pwyh1F3I0r4clFJXkSI8bOyJINGq github.com/sassoftware/relic v7.2.1+incompatible/go.mod h1:CWfAxv73/iLZ17rbyhIEq3K9hs5w6FpNMdUT//qR+zk= github.com/sassoftware/relic/v7 v7.5.5 h1:2ZUM6ovo3STCAp0hZnO9nQY9lOB8OyfneeYIi4YUxMU= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/secure-systems-lab/go-securesystemslib v0.3.1/go.mod h1:o8hhjkbNl2gOamKUA/eNW3xUrntHT9L4W89W1nfj43U= github.com/secure-systems-lab/go-securesystemslib v0.7.0 h1:OwvJ5jQf9LnIAS83waAjPbcMsODrTQUpJ02eNLUoxBg= github.com/secure-systems-lab/go-securesystemslib v0.7.0/go.mod h1:/2gYnlnHVQ6xeGtfIqFy7Do03K4cdCY0A/GlJLDKLHI= @@ -1553,7 +1512,6 @@ github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= @@ -1578,7 +1536,6 @@ github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.7.2 h1:GquAXZRIVJ8e github.com/sigstore/timestamp-authority v1.1.2 h1:xgBs9Ct27sEgFb35GL1trKD2XOgYbtk0q2G0HLZHDDY= github.com/sigstore/timestamp-authority v1.1.2/go.mod h1:7rGe/e6ZJNMqPiwFiv7w+qNXT8GID9gL7nMcRwZ007I= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -1594,13 +1551,10 @@ github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1 github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= -github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= -github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sosedoff/gitkit v0.4.0 h1:opyQJ/h9xMRLsz2ca/2CRXtstePcpldiZN8DpLLF8Os= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -1688,13 +1642,6 @@ github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0= github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs= -github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= -github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk= -github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk= -github.com/tj/go-buffer v1.1.0/go.mod h1:iyiJpfFcR2B9sXu7KvjbT9fpM4mOelRSDTbntVj52Uc= -github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= -github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= -github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM= github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -1706,16 +1653,9 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= -github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.25.5 h1:d0NIAyhh5shGscroL7ek/Ya9QYQE0KNabJgiUinIQkc= github.com/urfave/cli/v2 v2.25.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= -github.com/vbatts/go-mtree v0.5.0/go.mod h1:7JbaNHyBMng+RP8C3Q4E+4Ca8JnGQA2R/MB+jb4tSOk= -github.com/vbatts/go-mtree v0.5.2 h1:d8SAbLJiR1cR3pe1J+FBaalRkCQw95gP12/P+a9PUcA= -github.com/vbatts/go-mtree v0.5.2/go.mod h1:e0NDJ+bT3jG7ZINeB9HR5AxTvjskCsOR54+9KoaXyDc= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= github.com/vbauerster/mpb/v8 v8.6.1 h1:XbBpIbJxJOO9yMcKPpI4oEFPW6tLAptefNQJNcGWri8= @@ -1723,8 +1663,6 @@ github.com/vbauerster/mpb/v8 v8.6.1/go.mod h1:S0tuIjikxlLxCeNijNhwAuD/BB3UE/d2ny github.com/vektah/gqlparser/v2 v2.5.10 h1:6zSM4azXC9u4Nxy5YmdmGu4uKamfwsdKTwp5zsEealU= github.com/vektah/gqlparser/v2 v2.5.10/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= github.com/veraison/go-cose v1.1.0 h1:AalPS4VGiKavpAzIlBjrn7bhqXiXi4jbMYY/2+UC+4o= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= @@ -1849,7 +1787,6 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1859,7 +1796,6 @@ golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -2056,7 +1992,6 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2064,7 +1999,6 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2086,7 +2020,6 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201005172224-997123666555/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2105,7 +2038,6 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/pkg/api/controller_test.go b/pkg/api/controller_test.go index 29cc9ee7..8d342327 100644 --- a/pkg/api/controller_test.go +++ b/pkg/api/controller_test.go @@ -4350,7 +4350,7 @@ func TestInvalidCases(t *testing.T) { panic(err) } - digest := test.GetTestBlobDigest("zot-cve-test", "config").String() + digest := godigest.FromString("dummy").String() name := "zot-c-test" client := resty.New() @@ -4449,7 +4449,8 @@ func TestCrossRepoMount(t *testing.T) { ctlr.Config.Storage.RemoteCache = false ctlr.Config.Storage.Dedupe = false - err := test.WriteImageToFileSystem(CreateDefaultImage(), "zot-cve-test", "test", storage.StoreController{ + image := CreateDefaultImage() + err := test.WriteImageToFileSystem(image, "zot-cve-test", "test", storage.StoreController{ DefaultStore: test.GetDefaultImageStore(dir, ctlr.Log), }) So(err, ShouldBeNil) @@ -4459,8 +4460,7 @@ func TestCrossRepoMount(t *testing.T) { params := make(map[string]string) - var manifestDigest godigest.Digest - manifestDigest, _, _ = test.GetOciLayoutDigests(path.Join(dir, "zot-cve-test")) + manifestDigest := image.ManifestDescriptor.Digest dgst := manifestDigest name := "zot-cve-test" @@ -4487,7 +4487,7 @@ func TestCrossRepoMount(t *testing.T) { baseURL, constants.RoutePrefix, constants.Blobs, constants.Uploads)) incorrectParams := make(map[string]string) - incorrectParams["mount"] = test.GetTestBlobDigest("zot-cve-test", "manifest").String() + incorrectParams["mount"] = godigest.FromString("dummy").String() incorrectParams["from"] = "zot-x-test" postResponse, err = client.R(). diff --git a/pkg/extensions/extension_scrub.go b/pkg/extensions/extension_scrub.go index 1d67acde..bc61ad1f 100644 --- a/pkg/extensions/extension_scrub.go +++ b/pkg/extensions/extension_scrub.go @@ -28,25 +28,19 @@ func EnableScrubExtension(config *config.Config, log log.Logger, storeController log.Warn().Msg("Scrub interval set to too-short interval < 2h, changing scrub duration to 2 hours and continuing.") //nolint:lll // gofumpt conflicts with lll } - // is local imagestore (because of umoci dependency which works only locally) - if config.Storage.StorageDriver == nil { - generator := &taskGenerator{ - imgStore: storeController.DefaultStore, - log: log, - } - sch.SubmitGenerator(generator, config.Extensions.Scrub.Interval, scheduler.LowPriority) + generator := &taskGenerator{ + imgStore: storeController.DefaultStore, + log: log, } + sch.SubmitGenerator(generator, config.Extensions.Scrub.Interval, scheduler.LowPriority) if config.Storage.SubPaths != nil { for route := range config.Storage.SubPaths { - // is local imagestore (because of umoci dependency which works only locally) - if config.Storage.SubPaths[route].StorageDriver == nil { - generator := &taskGenerator{ - imgStore: storeController.SubStore[route], - log: log, - } - sch.SubmitGenerator(generator, config.Extensions.Scrub.Interval, scheduler.LowPriority) + generator := &taskGenerator{ + imgStore: storeController.SubStore[route], + log: log, } + sch.SubmitGenerator(generator, config.Extensions.Scrub.Interval, scheduler.LowPriority) } } } else { diff --git a/pkg/extensions/scrub/scrub.go b/pkg/extensions/scrub/scrub.go index 35d7f3d6..a683fb62 100644 --- a/pkg/extensions/scrub/scrub.go +++ b/pkg/extensions/scrub/scrub.go @@ -39,6 +39,7 @@ func RunScrubRepo(ctx context.Context, imgStore storageTypes.ImageStore, repo st Str("image", result.ImageName). Str("tag", result.Tag). Str("status", result.Status). + Str("affected blob", result.AffectedBlob). Str("error", result.Error). Msg("scrub: blobs/manifest affected") } diff --git a/pkg/extensions/search/search_test.go b/pkg/extensions/search/search_test.go index aafbc48b..642914ba 100644 --- a/pkg/extensions/search/search_test.go +++ b/pkg/extensions/search/search_test.go @@ -381,19 +381,21 @@ func TestRepoListWithNewestImage(t *testing.T) { ctlrManager.StartAndWait(port) defer ctlrManager.StopServer() - config, layers, manifest, err := GetImageComponents(100) + config, layers, _, err := GetImageComponents(100) So(err, ShouldBeNil) - err = UploadImage(Image{Manifest: manifest, Config: config, Layers: layers}, baseURL, "zot-cve-test", "0.0.1") + uploadedImage := CreateImageWith().LayerBlobs(layers).ImageConfig(config).Build() + + err = UploadImage(uploadedImage, baseURL, "zot-cve-test", "0.0.1") So(err, ShouldBeNil) - err = UploadImage(Image{Manifest: manifest, Config: config, Layers: layers}, baseURL, "a/zot-cve-test", "0.0.1") + err = UploadImage(uploadedImage, baseURL, "a/zot-cve-test", "0.0.1") So(err, ShouldBeNil) - err = UploadImage(Image{Manifest: manifest, Config: config, Layers: layers}, baseURL, "zot-test", "0.0.1") + err = UploadImage(uploadedImage, baseURL, "zot-test", "0.0.1") So(err, ShouldBeNil) - err = UploadImage(Image{Manifest: manifest, Config: config, Layers: layers}, baseURL, "a/zot-test", "0.0.1") + err = UploadImage(uploadedImage, baseURL, "a/zot-test", "0.0.1") So(err, ShouldBeNil) resp, err := resty.R().Get(baseURL + "/v2/") @@ -590,9 +592,8 @@ func TestRepoListWithNewestImage(t *testing.T) { panic(err) } - var manifestDigest godigest.Digest - var configDigest godigest.Digest - manifestDigest, configDigest, _ = GetOciLayoutDigests(path.Join(subRootDir, "a/zot-test")) + manifestDigest := uploadedImage.ManifestDescriptor.Digest + configDigest := uploadedImage.ConfigDescriptor.Digest // Delete config blob and try. err = os.Remove(path.Join(subRootDir, "a/zot-test/blobs/sha256", configDigest.Encoded())) @@ -1269,22 +1270,25 @@ func TestExpandedRepoInfo(t *testing.T) { ctlrManager.StartAndWait(port) defer ctlrManager.StopServer() - config, layers, manifest, err := GetImageComponents(100) + config, layers, _, err := GetImageComponents(100) So(err, ShouldBeNil) - manifest.Annotations = make(map[string]string) - manifest.Annotations["org.opencontainers.image.vendor"] = "zot" + annotations := make(map[string]string) + annotations["org.opencontainers.image.vendor"] = "zot" - err = UploadImage(Image{Manifest: manifest, Config: config, Layers: layers}, baseURL, "zot-cve-test", "0.0.1") + uploadedImage := CreateImageWith().LayerBlobs(layers).ImageConfig(config). + Annotations(annotations).Build() + + err = UploadImage(uploadedImage, baseURL, "zot-cve-test", "0.0.1") So(err, ShouldBeNil) - err = UploadImage(Image{Manifest: manifest, Config: config, Layers: layers}, baseURL, "a/zot-cve-test", "0.0.1") + err = UploadImage(uploadedImage, baseURL, "a/zot-cve-test", "0.0.1") So(err, ShouldBeNil) - err = UploadImage(Image{Manifest: manifest, Config: config, Layers: layers}, baseURL, "zot-test", "0.0.1") + err = UploadImage(uploadedImage, baseURL, "zot-test", "0.0.1") So(err, ShouldBeNil) - err = UploadImage(Image{Manifest: manifest, Config: config, Layers: layers}, baseURL, "a/zot-test", "0.0.1") + err = UploadImage(uploadedImage, baseURL, "a/zot-test", "0.0.1") So(err, ShouldBeNil) log := log.NewLogger("debug", "") @@ -1455,8 +1459,7 @@ func TestExpandedRepoInfo(t *testing.T) { } So(found, ShouldEqual, true) - var manifestDigest godigest.Digest - manifestDigest, _, _ = GetOciLayoutDigests(path.Join(rootDir, "zot-test")) + manifestDigest := uploadedImage.ManifestDescriptor.Digest err = os.Remove(path.Join(rootDir, "zot-test/blobs/sha256", manifestDigest.Encoded())) So(err, ShouldBeNil) diff --git a/pkg/storage/scrub.go b/pkg/storage/scrub.go index 7ec34e16..3c4f31c6 100644 --- a/pkg/storage/scrub.go +++ b/pkg/storage/scrub.go @@ -5,16 +5,12 @@ import ( "encoding/json" "fmt" "io" - "os" - "path" "strings" "time" "github.com/olekukonko/tablewriter" godigest "github.com/opencontainers/go-digest" ispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/opencontainers/umoci" - "github.com/opencontainers/umoci/oci/casext" "zotregistry.io/zot/errors" storageTypes "zotregistry.io/zot/pkg/storage/types" @@ -24,19 +20,22 @@ const ( colImageNameIndex = iota colTagIndex colStatusIndex + colAffectedBlobIndex colErrorIndex - imageNameWidth = 32 - tagWidth = 24 - statusWidth = 8 - errorWidth = 8 + imageNameWidth = 32 + tagWidth = 24 + statusWidth = 8 + affectedBlobWidth = 24 + errorWidth = 8 ) type ScrubImageResult struct { - ImageName string `json:"imageName"` - Tag string `json:"tag"` - Status string `json:"status"` - Error string `json:"error"` + ImageName string `json:"imageName"` + Tag string `json:"tag"` + Status string `json:"status"` + AffectedBlob string `json:"affectedBlob"` + Error string `json:"error"` } type ScrubResults struct { @@ -92,153 +91,228 @@ func CheckRepo(ctx context.Context, imageName string, imgStore storageTypes.Imag return results, ctx.Err() } - dir := path.Join(imgStore.RootDir(), imageName) - if !imgStore.DirExists(dir) { - return results, errors.ErrRepoNotFound - } - - oci, err := umoci.OpenLayout(dir) - if err != nil { - return results, err - } - - defer oci.Close() - var lockLatency time.Time imgStore.RLock(&lockLatency) defer imgStore.RUnlock(&lockLatency) - buf, err := os.ReadFile(path.Join(dir, "index.json")) + // check image structure / layout + ok, err := imgStore.ValidateRepo(imageName) + if err != nil { + return results, err + } + + if !ok { + return results, errors.ErrRepoBadLayout + } + + // check "index.json" content + indexContent, err := imgStore.GetIndexContent(imageName) if err != nil { return results, err } var index ispec.Index - if err := json.Unmarshal(buf, &index); err != nil { + if err := json.Unmarshal(indexContent, &index); err != nil { return results, errors.ErrRepoNotFound } - listOfManifests := []ispec.Descriptor{} + scrubbedManifests := make(map[godigest.Digest]ScrubImageResult) for _, manifest := range index.Manifests { - if manifest.MediaType == ispec.MediaTypeImageIndex { - buf, err := os.ReadFile(path.Join(dir, "blobs", manifest.Digest.Algorithm().String(), manifest.Digest.Encoded())) - if err != nil { - tagName := manifest.Annotations[ispec.AnnotationRefName] - imgRes := getResult(imageName, tagName, errors.ErrBadBlobDigest) - results = append(results, imgRes) - - continue - } - - var idx ispec.Index - if err := json.Unmarshal(buf, &idx); err != nil { - tagName := manifest.Annotations[ispec.AnnotationRefName] - imgRes := getResult(imageName, tagName, errors.ErrBadBlobDigest) - results = append(results, imgRes) - - continue - } - - listOfManifests = append(listOfManifests, idx.Manifests...) - } else if manifest.MediaType == ispec.MediaTypeImageManifest { - listOfManifests = append(listOfManifests, manifest) - } - } - - for _, m := range listOfManifests { - tag := m.Annotations[ispec.AnnotationRefName] - imageResult := CheckIntegrity(ctx, imageName, tag, oci, m, dir) - results = append(results, imageResult) + tag := manifest.Annotations[ispec.AnnotationRefName] + scrubManifest(ctx, manifest, imgStore, imageName, tag, scrubbedManifests) + results = append(results, scrubbedManifests[manifest.Digest]) } return results, nil } -func CheckIntegrity(ctx context.Context, imageName, tagName string, oci casext.Engine, manifest ispec.Descriptor, dir string) ScrubImageResult { //nolint: lll +func scrubManifest( + ctx context.Context, manifest ispec.Descriptor, imgStore storageTypes.ImageStore, imageName, tag string, + scrubbedManifests map[godigest.Digest]ScrubImageResult, +) { + res, ok := scrubbedManifests[manifest.Digest] + if ok { + scrubbedManifests[manifest.Digest] = newScrubImageResult(imageName, tag, res.Status, + res.AffectedBlob, res.Error) + + return + } + + switch manifest.MediaType { + case ispec.MediaTypeImageIndex: + buf, err := imgStore.GetBlobContent(imageName, manifest.Digest) + if err != nil { + imgRes := getResult(imageName, tag, manifest.Digest, errors.ErrBadBlobDigest) + scrubbedManifests[manifest.Digest] = imgRes + + return + } + + var idx ispec.Index + if err := json.Unmarshal(buf, &idx); err != nil { + imgRes := getResult(imageName, tag, manifest.Digest, errors.ErrBadBlobDigest) + scrubbedManifests[manifest.Digest] = imgRes + + return + } + + // check all manifests + for _, m := range idx.Manifests { + scrubManifest(ctx, m, imgStore, imageName, tag, scrubbedManifests) + + // if the manifest is affected then this index is also affected + if scrubbedManifests[m.Digest].Error != "" { + mRes := scrubbedManifests[m.Digest] + + scrubbedManifests[manifest.Digest] = newScrubImageResult(imageName, tag, mRes.Status, + mRes.AffectedBlob, mRes.Error) + + return + } + } + + // at this point, before starting to check de subject we can consider the index is ok + scrubbedManifests[manifest.Digest] = getResult(imageName, tag, "", nil) + + // check subject if exists + if idx.Subject != nil { + scrubManifest(ctx, *idx.Subject, imgStore, imageName, tag, scrubbedManifests) + + subjectRes := scrubbedManifests[idx.Subject.Digest] + + scrubbedManifests[manifest.Digest] = newScrubImageResult(imageName, tag, subjectRes.Status, + subjectRes.AffectedBlob, subjectRes.Error) + } + case ispec.MediaTypeImageManifest: + imgRes := CheckIntegrity(ctx, imageName, tag, manifest, imgStore) + scrubbedManifests[manifest.Digest] = imgRes + + // if integrity ok then check subject if exists + if imgRes.Error == "" { + manifestContent, _ := imgStore.GetBlobContent(imageName, manifest.Digest) + + var man ispec.Manifest + + _ = json.Unmarshal(manifestContent, &man) + + if man.Subject != nil { + scrubManifest(ctx, *man.Subject, imgStore, imageName, tag, scrubbedManifests) + + subjectRes := scrubbedManifests[man.Subject.Digest] + + scrubbedManifests[manifest.Digest] = newScrubImageResult(imageName, tag, subjectRes.Status, + subjectRes.AffectedBlob, subjectRes.Error) + } + } + default: + scrubbedManifests[manifest.Digest] = getResult(imageName, tag, manifest.Digest, errors.ErrBadManifest) + } +} + +func CheckIntegrity( + ctx context.Context, imageName, tagName string, manifest ispec.Descriptor, imgStore storageTypes.ImageStore, +) ScrubImageResult { // check manifest and config - if _, err := umoci.Stat(ctx, oci, manifest); err != nil { - return getResult(imageName, tagName, err) + if affectedBlob, err := CheckManifestAndConfig(imageName, manifest, imgStore); err != nil { + return getResult(imageName, tagName, affectedBlob, err) } // check layers - return CheckLayers(ctx, imageName, tagName, dir, manifest) + return CheckLayers(ctx, imageName, tagName, manifest, imgStore) } -func CheckLayers(ctx context.Context, imageName, tagName, dir string, manifest ispec.Descriptor) ScrubImageResult { +func CheckManifestAndConfig( + imageName string, manifestDesc ispec.Descriptor, imgStore storageTypes.ImageStore, +) (godigest.Digest, error) { + if manifestDesc.MediaType != ispec.MediaTypeImageManifest { + return manifestDesc.Digest, errors.ErrBadManifest + } + + manifestContent, err := imgStore.GetBlobContent(imageName, manifestDesc.Digest) + if err != nil { + return manifestDesc.Digest, err + } + + var manifest ispec.Manifest + + err = json.Unmarshal(manifestContent, &manifest) + if err != nil { + return manifestDesc.Digest, errors.ErrBadManifest + } + + configContent, err := imgStore.GetBlobContent(imageName, manifest.Config.Digest) + if err != nil { + return manifest.Config.Digest, err + } + + var config ispec.Image + + err = json.Unmarshal(configContent, &config) + if err != nil { + return manifest.Config.Digest, errors.ErrBadConfig + } + + return "", nil +} + +func CheckLayers( + ctx context.Context, imageName, tagName string, manifest ispec.Descriptor, imgStore storageTypes.ImageStore, +) ScrubImageResult { imageRes := ScrubImageResult{} - buf, err := os.ReadFile(path.Join(dir, "blobs", manifest.Digest.Algorithm().String(), manifest.Digest.Encoded())) + buf, err := imgStore.GetBlobContent(imageName, manifest.Digest) if err != nil { - imageRes = getResult(imageName, tagName, err) + imageRes = getResult(imageName, tagName, manifest.Digest, err) return imageRes } var man ispec.Manifest if err := json.Unmarshal(buf, &man); err != nil { - imageRes = getResult(imageName, tagName, err) + imageRes = getResult(imageName, tagName, manifest.Digest, errors.ErrBadManifest) return imageRes } for _, layer := range man.Layers { - layerPath := path.Join(dir, "blobs", layer.Digest.Algorithm().String(), layer.Digest.Encoded()) - - _, err = os.Stat(layerPath) + layerContent, err := imgStore.GetBlobContent(imageName, layer.Digest) if err != nil { - imageRes = getResult(imageName, tagName, errors.ErrBlobNotFound) + imageRes = getResult(imageName, tagName, layer.Digest, err) break } - layerFh, err := os.Open(layerPath) - if err != nil { - imageRes = getResult(imageName, tagName, errors.ErrBlobNotFound) - - break - } - - computedDigest, err := godigest.FromReader(layerFh) - layerFh.Close() - - if err != nil { - imageRes = getResult(imageName, tagName, errors.ErrBadBlobDigest) - - break - } + computedDigest := godigest.FromBytes(layerContent) if computedDigest != layer.Digest { - imageRes = getResult(imageName, tagName, errors.ErrBadBlobDigest) + imageRes = getResult(imageName, tagName, layer.Digest, errors.ErrBadBlobDigest) break } - imageRes = getResult(imageName, tagName, nil) + imageRes = getResult(imageName, tagName, "", nil) } return imageRes } -func getResult(imageName, tag string, err error) ScrubImageResult { - var status string - - var errField string - +func getResult(imageName, tag string, affectedBlobDigest godigest.Digest, err error) ScrubImageResult { if err != nil { - status = "affected" - errField = err.Error() - } else { - status = "ok" - errField = "" + return newScrubImageResult(imageName, tag, "affected", affectedBlobDigest.Encoded(), err.Error()) } + return newScrubImageResult(imageName, tag, "ok", "", "") +} + +func newScrubImageResult(imageName, tag, status, affectedBlob, err string) ScrubImageResult { return ScrubImageResult{ - ImageName: imageName, - Tag: tag, - Status: status, - Error: errField, + ImageName: imageName, + Tag: tag, + Status: status, + AffectedBlob: affectedBlob, + Error: err, } } @@ -259,12 +333,13 @@ func getScrubTableWriter(writer io.Writer) *tablewriter.Table { table.SetColMinWidth(colImageNameIndex, imageNameWidth) table.SetColMinWidth(colTagIndex, tagWidth) table.SetColMinWidth(colStatusIndex, statusWidth) + table.SetColMinWidth(colErrorIndex, affectedBlobWidth) table.SetColMinWidth(colErrorIndex, errorWidth) return table } -const tableCols = 4 +const tableCols = 5 func printScrubTableHeader(writer io.Writer) { table := getScrubTableWriter(writer) @@ -274,6 +349,7 @@ func printScrubTableHeader(writer io.Writer) { row[colImageNameIndex] = "REPOSITORY" row[colTagIndex] = "TAG" row[colStatusIndex] = "STATUS" + row[colAffectedBlobIndex] = "AFFECTED BLOB" row[colErrorIndex] = "ERROR" table.Append(row) @@ -287,6 +363,7 @@ func printImageResult(imageResult ScrubImageResult) string { table.SetColMinWidth(colImageNameIndex, imageNameWidth) table.SetColMinWidth(colTagIndex, tagWidth) table.SetColMinWidth(colStatusIndex, statusWidth) + table.SetColMinWidth(colAffectedBlobIndex, affectedBlobWidth) table.SetColMinWidth(colErrorIndex, errorWidth) row := make([]string, tableCols) @@ -294,6 +371,7 @@ func printImageResult(imageResult ScrubImageResult) string { row[colImageNameIndex] = imageResult.ImageName row[colTagIndex] = imageResult.Tag row[colStatusIndex] = imageResult.Status + row[colAffectedBlobIndex] = imageResult.AffectedBlob row[colErrorIndex] = imageResult.Error table.Append(row) diff --git a/pkg/storage/scrub_test.go b/pkg/storage/scrub_test.go index 9d9b73ef..68f1de0a 100644 --- a/pkg/storage/scrub_test.go +++ b/pkg/storage/scrub_test.go @@ -4,23 +4,31 @@ import ( "bytes" "context" "encoding/json" - "os" + "errors" + "fmt" "path" "regexp" "strings" "testing" + "github.com/docker/distribution/registry/storage/driver" + guuid "github.com/gofrs/uuid" godigest "github.com/opencontainers/go-digest" ispec "github.com/opencontainers/image-spec/specs-go/v1" . "github.com/smartystreets/goconvey/convey" + zerr "zotregistry.io/zot/errors" "zotregistry.io/zot/pkg/extensions/monitoring" "zotregistry.io/zot/pkg/log" "zotregistry.io/zot/pkg/storage" "zotregistry.io/zot/pkg/storage/cache" common "zotregistry.io/zot/pkg/storage/common" "zotregistry.io/zot/pkg/storage/local" + "zotregistry.io/zot/pkg/storage/s3" + storageTypes "zotregistry.io/zot/pkg/storage/types" "zotregistry.io/zot/pkg/test" + . "zotregistry.io/zot/pkg/test/image-utils" + "zotregistry.io/zot/pkg/test/mocks" ) const ( @@ -28,31 +36,60 @@ const ( tag = "1.0" ) -func TestCheckAllBlobsIntegrity(t *testing.T) { - dir := t.TempDir() +var errUnexpectedError = errors.New("unexpected err") - log := log.NewLogger("debug", "") +func TestLocalCheckAllBlobsIntegrity(t *testing.T) { + Convey("test with local storage", t, func() { + tdir := t.TempDir() + log := log.NewLogger("debug", "") + metrics := monitoring.NewMetricsServer(false, log) + cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{ + RootDir: tdir, + Name: "cache", + UseRelPaths: true, + }, log) + driver := local.New(true) + imgStore := local.NewImageStore(tdir, true, true, log, metrics, nil, cacheDriver) - metrics := monitoring.NewMetricsServer(false, log) - cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{ - RootDir: dir, - Name: "cache", - UseRelPaths: true, - }, log) - imgStore := local.NewImageStore(dir, true, true, log, metrics, nil, cacheDriver) + RunCheckAllBlobsIntegrityTests(t, imgStore, driver, log) + }) +} - Convey("Scrub only one repo", t, func(c C) { +func TestS3CheckAllBlobsIntegrity(t *testing.T) { + skipIt(t) + + Convey("test with S3 storage", t, func() { + uuid, err := guuid.NewV4() + if err != nil { + panic(err) + } + + testDir := path.Join("/oci-repo-test", uuid.String()) + tdir := t.TempDir() + log := log.NewLogger("debug", "") + + var store driver.StorageDriver + store, imgStore, _ := createObjectsStore(testDir, tdir) + defer cleanupStorage(store, testDir) + + driver := s3.New(store) + + RunCheckAllBlobsIntegrityTests(t, imgStore, driver, log) + }) +} + +func RunCheckAllBlobsIntegrityTests( //nolint: thelper + t *testing.T, imgStore storageTypes.ImageStore, driver storageTypes.Driver, log log.Logger, +) { + Convey("Scrub only one repo", func() { // initialize repo err := imgStore.InitRepo(repoName) So(err, ShouldBeNil) ok := imgStore.DirExists(path.Join(imgStore.RootDir(), repoName)) So(ok, ShouldBeTrue) - storeController := storage.StoreController{} - storeController.DefaultStore = imgStore - So(storeController.GetImageStore(repoName), ShouldResemble, imgStore) - storeCtlr := storage.StoreController{} storeCtlr.DefaultStore = imgStore + So(storeCtlr.GetImageStore(repoName), ShouldResemble, imgStore) config, layers, manifest, err := test.GetImageComponents(1000) //nolint:staticcheck So(err, ShouldBeNil) @@ -84,7 +121,7 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") So(actual, ShouldContainSubstring, "test 1.0 ok") }) @@ -96,9 +133,15 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { // delete content of manifest file manifestDig := manifestDigest.Encoded() manifestFile := path.Join(imgStore.RootDir(), repoName, "/blobs/sha256", manifestDig) - err = os.Truncate(manifestFile, 0) + err = driver.Delete(manifestFile) So(err, ShouldBeNil) + defer func() { + // put manifest content back to file + _, err = driver.WriteFile(manifestFile, content) + So(err, ShouldBeNil) + }() + buff := bytes.NewBufferString("") res, err := storeCtlr.CheckAllBlobsIntegrity(context.Background()) @@ -108,9 +151,9 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") // verify error message - So(actual, ShouldContainSubstring, "test 1.0 affected parse application/vnd.oci.image.manifest.v1+json") + So(actual, ShouldContainSubstring, fmt.Sprintf("test 1.0 affected %s blob: not found", manifestDig)) index, err := common.GetIndex(imgStore, repoName, log) So(err, ShouldBeNil) @@ -118,14 +161,34 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { So(len(index.Manifests), ShouldEqual, 1) manifestDescriptor := index.Manifests[0] - repoDir := path.Join(dir, repoName) - imageRes := storage.CheckLayers(context.Background(), repoName, tag, repoDir, manifestDescriptor) + imageRes := storage.CheckLayers(context.Background(), repoName, tag, manifestDescriptor, imgStore) So(imageRes.Status, ShouldEqual, "affected") - So(imageRes.Error, ShouldEqual, "unexpected end of JSON input") + So(imageRes.Error, ShouldEqual, "blob: not found") - // put manifest content back to file - err = os.WriteFile(manifestFile, content, 0o600) + _, err = driver.WriteFile(manifestFile, []byte("invalid content")) So(err, ShouldBeNil) + + buff = bytes.NewBufferString("") + + res, err = storeCtlr.CheckAllBlobsIntegrity(context.Background()) + res.PrintScrubResults(buff) + So(err, ShouldBeNil) + + str = space.ReplaceAllString(buff.String(), " ") + actual = strings.TrimSpace(str) + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") + // verify error message + So(actual, ShouldContainSubstring, fmt.Sprintf("test 1.0 affected %s manifest: invalid contents", manifestDig)) + + index, err = common.GetIndex(imgStore, repoName, log) + So(err, ShouldBeNil) + + So(len(index.Manifests), ShouldEqual, 1) + manifestDescriptor = index.Manifests[0] + + imageRes = storage.CheckLayers(context.Background(), repoName, tag, manifestDescriptor, imgStore) + So(imageRes.Status, ShouldEqual, "affected") + So(imageRes.Error, ShouldEqual, "manifest: invalid contents") }) Convey("Config integrity affected", func() { @@ -136,9 +199,15 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { // delete content of config file configDig := configDigest.Encoded() configFile := path.Join(imgStore.RootDir(), repoName, "/blobs/sha256", configDig) - err = os.Truncate(configFile, 0) + err = driver.Delete(configFile) So(err, ShouldBeNil) + defer func() { + // put config content back to file + _, err = driver.WriteFile(configFile, content) + So(err, ShouldBeNil) + }() + buff := bytes.NewBufferString("") res, err := storeCtlr.CheckAllBlobsIntegrity(context.Background()) @@ -148,12 +217,22 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") - So(actual, ShouldContainSubstring, "test 1.0 affected stat: parse application/vnd.oci.image.config.v1+json") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") + So(actual, ShouldContainSubstring, fmt.Sprintf("test 1.0 affected %s blob: not found", configDig)) - // put config content back to file - err = os.WriteFile(configFile, content, 0o600) + _, err = driver.WriteFile(configFile, []byte("invalid content")) So(err, ShouldBeNil) + + buff = bytes.NewBufferString("") + + res, err = storeCtlr.CheckAllBlobsIntegrity(context.Background()) + res.PrintScrubResults(buff) + So(err, ShouldBeNil) + + str = space.ReplaceAllString(buff.String(), " ") + actual = strings.TrimSpace(str) + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") + So(actual, ShouldContainSubstring, fmt.Sprintf("test 1.0 affected %s config: invalid config", configDig)) }) Convey("Layers integrity affected", func() { @@ -164,9 +243,15 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { // delete content of layer file layerDig := layerDigest.Encoded() layerFile := path.Join(imgStore.RootDir(), repoName, "/blobs/sha256", layerDig) - err = os.Truncate(layerFile, 0) + _, err = driver.WriteFile(layerFile, []byte(" ")) So(err, ShouldBeNil) + defer func() { + // put layer content back to file + _, err = driver.WriteFile(layerFile, content) + So(err, ShouldBeNil) + }() + buff := bytes.NewBufferString("") res, err := storeCtlr.CheckAllBlobsIntegrity(context.Background()) @@ -176,37 +261,36 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") - So(actual, ShouldContainSubstring, "test 1.0 affected blob: bad blob digest") - - // put layer content back to file - err = os.WriteFile(layerFile, content, 0o600) - So(err, ShouldBeNil) + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") + So(actual, ShouldContainSubstring, fmt.Sprintf("test 1.0 affected %s blob: bad blob digest", layerDig)) }) Convey("Layer not found", func() { + // get content of layer + content, err := imgStore.GetBlobContent(repoName, layerDigest) + So(err, ShouldBeNil) + // change layer file permissions layerDig := layerDigest.Encoded() - repoDir := path.Join(dir, repoName) + repoDir := path.Join(imgStore.RootDir(), repoName) layerFile := path.Join(repoDir, "/blobs/sha256", layerDig) - err = os.Chmod(layerFile, 0x0200) + err = driver.Delete(layerFile) So(err, ShouldBeNil) + defer func() { + _, err := driver.WriteFile(layerFile, content) + So(err, ShouldBeNil) + }() + index, err := common.GetIndex(imgStore, repoName, log) So(err, ShouldBeNil) So(len(index.Manifests), ShouldEqual, 1) manifestDescriptor := index.Manifests[0] - imageRes := storage.CheckLayers(context.Background(), repoName, tag, repoDir, manifestDescriptor) + imageRes := storage.CheckLayers(context.Background(), repoName, tag, manifestDescriptor, imgStore) So(imageRes.Status, ShouldEqual, "affected") So(imageRes.Error, ShouldEqual, "blob: not found") - err = os.Chmod(layerFile, 0x0600) - So(err, ShouldBeNil) - - // delete layer file - err = os.Remove(layerFile) - So(err, ShouldBeNil) buff := bytes.NewBufferString("") @@ -217,8 +301,8 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") - So(actual, ShouldContainSubstring, "test 1.0 affected blob: not found") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") + So(actual, ShouldContainSubstring, fmt.Sprintf("test 1.0 affected %s blob: not found", layerDig)) }) Convey("Scrub index", func() { @@ -244,8 +328,15 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { _, _, err = imgStore.FullBlobUpload(repoName, newManifestReader, newManifestDigest) So(err, ShouldBeNil) + idx, err := common.GetIndex(imgStore, repoName, log) + So(err, ShouldBeNil) + + manifestDescriptor, ok := common.GetManifestDescByReference(idx, manifestDigest.String()) + So(ok, ShouldBeTrue) + var index ispec.Index index.SchemaVersion = 2 + index.Subject = &manifestDescriptor index.Manifests = []ispec.Descriptor{ { MediaType: ispec.MediaTypeImageManifest, @@ -268,13 +359,14 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") So(actual, ShouldContainSubstring, "test 1.0 ok") So(actual, ShouldContainSubstring, "test ok") // test scrub index - errors - indexFile := path.Join(imgStore.RootDir(), repoName, "/blobs/sha256", indexDigest.Encoded()) - err = os.Chmod(indexFile, 0o000) + // delete content of manifest file + manifestFile := path.Join(imgStore.RootDir(), repoName, "/blobs/sha256", newManifestDigest.Encoded()) + err = driver.Delete(manifestFile) So(err, ShouldBeNil) buff = bytes.NewBufferString("") @@ -285,13 +377,11 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { str = space.ReplaceAllString(buff.String(), " ") actual = strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") So(actual, ShouldContainSubstring, "test affected") - err = os.Chmod(indexFile, 0o600) - So(err, ShouldBeNil) - - err = os.Truncate(indexFile, 0) + indexFile := path.Join(imgStore.RootDir(), repoName, "/blobs/sha256", indexDigest.Encoded()) + err = driver.Delete(indexFile) So(err, ShouldBeNil) buff = bytes.NewBufferString("") @@ -302,7 +392,48 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { str = space.ReplaceAllString(buff.String(), " ") actual = strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") + So(actual, ShouldContainSubstring, "test affected") + + index.Manifests[0].MediaType = "invalid" + indexBlob, err = json.Marshal(index) + So(err, ShouldBeNil) + + _, err = driver.WriteFile(indexFile, indexBlob) + So(err, ShouldBeNil) + + buff = bytes.NewBufferString("") + + res, err = storeCtlr.CheckAllBlobsIntegrity(context.Background()) + res.PrintScrubResults(buff) + So(err, ShouldBeNil) + + _, err = storage.CheckManifestAndConfig(repoName, index.Manifests[0], imgStore) + So(err, ShouldNotBeNil) + So(err, ShouldEqual, zerr.ErrBadManifest) + + str = space.ReplaceAllString(buff.String(), " ") + actual = strings.TrimSpace(str) + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") + So(actual, ShouldContainSubstring, "test affected") + + _, err = driver.WriteFile(indexFile, []byte("invalid cotent")) + So(err, ShouldBeNil) + + defer func() { + err := driver.Delete(indexFile) + So(err, ShouldBeNil) + }() + + buff = bytes.NewBufferString("") + + res, err = storeCtlr.CheckAllBlobsIntegrity(context.Background()) + res.PrintScrubResults(buff) + So(err, ShouldBeNil) + + str = space.ReplaceAllString(buff.String(), " ") + actual = strings.TrimSpace(str) + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") So(actual, ShouldContainSubstring, "test affected") }) @@ -310,7 +441,7 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { // delete manifest file manifestDig := manifestDigest.Encoded() manifestFile := path.Join(imgStore.RootDir(), repoName, "/blobs/sha256", manifestDig) - err = os.Remove(manifestFile) + err = driver.Delete(manifestFile) So(err, ShouldBeNil) buff := bytes.NewBufferString("") @@ -322,20 +453,76 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") - So(actual, ShouldContainSubstring, "test 1.0 affected") - So(actual, ShouldContainSubstring, "no such file or directory") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") + So(actual, ShouldContainSubstring, fmt.Sprintf("test 1.0 affected %s blob: not found", manifestDig)) index, err := common.GetIndex(imgStore, repoName, log) So(err, ShouldBeNil) - So(len(index.Manifests), ShouldEqual, 2) + So(len(index.Manifests), ShouldEqual, 1) manifestDescriptor := index.Manifests[0] - repoDir := path.Join(dir, repoName) - imageRes := storage.CheckLayers(context.Background(), repoName, tag, repoDir, manifestDescriptor) + imageRes := storage.CheckLayers(context.Background(), repoName, tag, manifestDescriptor, imgStore) So(imageRes.Status, ShouldEqual, "affected") - So(imageRes.Error, ShouldContainSubstring, "no such file or directory") + So(imageRes.Error, ShouldContainSubstring, "blob: not found") + }) + + Convey("use the result of an already scrubed manifest which is the subject of the current manifest", func() { + index, err := common.GetIndex(imgStore, repoName, log) + So(err, ShouldBeNil) + + manifestDescriptor, ok := common.GetManifestDescByReference(index, manifestDigest.String()) + So(ok, ShouldBeTrue) + + err = test.WriteImageToFileSystem(CreateDefaultImageWith().Subject(&manifestDescriptor).Build(), + repoName, "0.0.1", storeCtlr) + So(err, ShouldBeNil) + + buff := bytes.NewBufferString("") + + res, err := storeCtlr.CheckAllBlobsIntegrity(context.Background()) + res.PrintScrubResults(buff) + So(err, ShouldBeNil) + + space := regexp.MustCompile(`\s+`) + str := space.ReplaceAllString(buff.String(), " ") + actual := strings.TrimSpace(str) + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") + So(actual, ShouldContainSubstring, "test 1.0 ok") + So(actual, ShouldContainSubstring, "test 0.0.1 ok") }) }) + + Convey("test errors", func() { + mockedImgStore := mocks.MockedImageStore{ + GetRepositoriesFn: func() ([]string, error) { + return []string{repoName}, nil + }, + ValidateRepoFn: func(name string) (bool, error) { + return false, nil + }, + } + + storeController := storage.StoreController{} + storeController.DefaultStore = mockedImgStore + + _, err := storeController.CheckAllBlobsIntegrity(context.Background()) + So(err, ShouldNotBeNil) + So(err, ShouldEqual, zerr.ErrRepoBadLayout) + + mockedImgStore = mocks.MockedImageStore{ + GetRepositoriesFn: func() ([]string, error) { + return []string{repoName}, nil + }, + GetIndexContentFn: func(repo string) ([]byte, error) { + return []byte{}, errUnexpectedError + }, + } + + storeController.DefaultStore = mockedImgStore + + _, err = storeController.CheckAllBlobsIntegrity(context.Background()) + So(err, ShouldNotBeNil) + So(err, ShouldEqual, errUnexpectedError) + }) } diff --git a/pkg/test/common.go b/pkg/test/common.go index 070bb8e1..97f0309a 100644 --- a/pkg/test/common.go +++ b/pkg/test/common.go @@ -35,7 +35,6 @@ import ( godigest "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/specs-go" ispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/opencontainers/umoci" "github.com/phayes/freeport" "github.com/project-zot/mockoidc" "github.com/sigstore/cosign/v2/cmd/cosign/cli/generate" @@ -72,29 +71,6 @@ var ( var NotationPathLock = new(sync.Mutex) //nolint: gochecknoglobals -// which: manifest, config, layer -func GetTestBlobDigest(image, which string) godigest.Digest { - prePath := "../test/data" - - for _, err := os.Stat(prePath); err != nil; _, err = os.Stat(prePath) { - prePath = "../" + prePath - } - - imgPath := path.Join(prePath, image) - manifest, config, layer := GetOciLayoutDigests(imgPath) - - switch which { - case "manifest": - return manifest - case "config": - return config - case "layer": - return layer - } - - return "" -} - func GetFreePort() string { port, err := freeport.GetFreePort() if err != nil { @@ -434,57 +410,6 @@ func GetRandomImageConfig() ([]byte, godigest.Digest) { return configBlobContent, configBlobDigestRaw } -func GetOciLayoutDigests(imagePath string) (godigest.Digest, godigest.Digest, godigest.Digest) { - var ( - manifestDigest godigest.Digest - configDigest godigest.Digest - layerDigest godigest.Digest - ) - - oci, err := umoci.OpenLayout(imagePath) - if err != nil { - panic(fmt.Errorf("error opening layout at '%s' : %w", imagePath, err)) - } - - defer oci.Close() - - ctxUmoci := context.Background() - - index, err := oci.GetIndex(ctxUmoci) - if err != nil { - panic(err) - } - - for _, manifest := range index.Manifests { - manifestDigest = manifest.Digest - - manifestBlob, err := oci.GetBlob(ctxUmoci, manifest.Digest) - if err != nil { - panic(err) - } - - manifestBuf, err := io.ReadAll(manifestBlob) - if err != nil { - panic(err) - } - - var manifest ispec.Manifest - - err = json.Unmarshal(manifestBuf, &manifest) - if err != nil { - panic(err) - } - - configDigest = manifest.Config.Digest - - for _, layer := range manifest.Layers { - layerDigest = layer.Digest - } - } - - return manifestDigest, configDigest, layerDigest -} - // Deprecated: Should use the new functions starting with "Create". func GetImageComponents(layerSize int) (ispec.Image, [][]byte, ispec.Manifest, error) { config := ispec.Image{ diff --git a/pkg/test/common_test.go b/pkg/test/common_test.go index 988af020..9f827bd7 100644 --- a/pkg/test/common_test.go +++ b/pkg/test/common_test.go @@ -22,7 +22,6 @@ import ( "zotregistry.io/zot/pkg/api" "zotregistry.io/zot/pkg/api/config" - "zotregistry.io/zot/pkg/log" "zotregistry.io/zot/pkg/storage" "zotregistry.io/zot/pkg/test" . "zotregistry.io/zot/pkg/test/image-utils" @@ -125,64 +124,6 @@ func TestCopyFiles(t *testing.T) { }) } -func TestGetOciLayoutDigests(t *testing.T) { - dir := t.TempDir() - - Convey("image path is wrong", t, func() { - So(func() { _, _, _ = test.GetOciLayoutDigests("inexistent-image") }, ShouldPanic) - }) - - Convey("no permissions when getting index", t, func() { - storageCtlr := test.GetDefaultStoreController(dir, log.NewLogger("debug", "")) - image := CreateDefaultImage() - - err := test.WriteImageToFileSystem(image, "test-index", "0.0.1", storageCtlr) - So(err, ShouldBeNil) - - err = os.Chmod(path.Join(dir, "test-index", "index.json"), 0o000) - if err != nil { - panic(err) - } - - So(func() { _, _, _ = test.GetOciLayoutDigests(path.Join(dir, "test-index")) }, ShouldPanic) - - err = os.Chmod(path.Join(dir, "test-index", "index.json"), 0o755) - if err != nil { - panic(err) - } - }) - - Convey("can't access manifest digest", t, func() { - storageCtlr := test.GetDefaultStoreController(dir, log.NewLogger("debug", "")) - image := CreateDefaultImage() - - err := test.WriteImageToFileSystem(image, "test-manifest", "0.0.1", storageCtlr) - So(err, ShouldBeNil) - - buf, err := os.ReadFile(path.Join(dir, "test-manifest", "index.json")) - if err != nil { - panic(err) - } - - var index ispec.Index - if err := json.Unmarshal(buf, &index); err != nil { - panic(err) - } - - err = os.Chmod(path.Join(dir, "test-manifest", "blobs/sha256", index.Manifests[0].Digest.Encoded()), 0o000) - if err != nil { - panic(err) - } - - So(func() { _, _, _ = test.GetOciLayoutDigests(path.Join(dir, "test-manifest")) }, ShouldPanic) - - err = os.Chmod(path.Join(dir, "test-manifest", "blobs/sha256", index.Manifests[0].Digest.Encoded()), 0o755) - if err != nil { - panic(err) - } - }) -} - func TestGetImageComponents(t *testing.T) { Convey("Inject failures for unreachable lines", t, func() { injected := inject.InjectFailure(0) diff --git a/pkg/test/oci-layout/oci_layout_test.go b/pkg/test/oci-layout/oci_layout_test.go index 7aa3067e..200c77ee 100644 --- a/pkg/test/oci-layout/oci_layout_test.go +++ b/pkg/test/oci-layout/oci_layout_test.go @@ -33,8 +33,6 @@ import ( var ErrTestError = fmt.Errorf("testError") func TestBaseOciLayoutUtils(t *testing.T) { - manifestDigest := GetTestBlobDigest("zot-test", "config").String() - Convey("GetImageManifestSize fail", t, func() { mockStoreController := mocks.MockedImageStore{ GetBlobContentFn: func(repo string, digest godigest.Digest) ([]byte, error) { @@ -64,6 +62,9 @@ func TestBaseOciLayoutUtils(t *testing.T) { }) Convey("GetImageConfigSize: config GetBlobContent fail", t, func() { + image := CreateRandomImage() + manifestDigest := image.ConfigDescriptor.Digest.String() + mockStoreController := mocks.MockedImageStore{ GetBlobContentFn: func(repo string, digest godigest.Digest) ([]byte, error) { if digest.String() == manifestDigest { @@ -83,7 +84,7 @@ func TestBaseOciLayoutUtils(t *testing.T) { "layers": [ { "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", - "digest": "` + GetTestBlobDigest("zot-test", "layer").String() + `", + "digest": "` + image.Manifest.Layers[0].Digest.String() + `", "size": 76097157 } ]