diff -Nru docker-registry-2.7.1+ds2/blobs.go docker-registry-2.8.0+ds1/blobs.go --- docker-registry-2.7.1+ds2/blobs.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/blobs.go 2022-02-07 15:40:21.000000000 +0000 @@ -10,7 +10,7 @@ "github.com/docker/distribution/reference" "github.com/opencontainers/go-digest" - "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) var ( diff -Nru docker-registry-2.7.1+ds2/cmd/registry-api-descriptor-template/main.go docker-registry-2.8.0+ds1/cmd/registry-api-descriptor-template/main.go --- docker-registry-2.7.1+ds2/cmd/registry-api-descriptor-template/main.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/cmd/registry-api-descriptor-template/main.go 2022-02-07 15:40:21.000000000 +0000 @@ -21,7 +21,7 @@ "text/template" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" ) var spaceRegex = regexp.MustCompile(`\n\s*`) diff -Nru docker-registry-2.7.1+ds2/configuration/configuration.go docker-registry-2.8.0+ds1/configuration/configuration.go --- docker-registry-2.7.1+ds2/configuration/configuration.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/configuration/configuration.go 2022-02-07 15:40:21.000000000 +0000 @@ -108,6 +108,12 @@ // A file may contain multiple CA certificates encoded as PEM ClientCAs []string `yaml:"clientcas,omitempty"` + // Specifies the lowest TLS version allowed + MinimumTLS string `yaml:"minimumtls,omitempty"` + + // Specifies a list of cipher suites allowed + CipherSuites []string `yaml:"ciphersuites,omitempty"` + // LetsEncrypt is used to configuration setting up TLS through // Let's Encrypt instead of manually specifying certificate and // key. If a TLS certificate is specified, the Let's Encrypt @@ -388,7 +394,7 @@ switch loglevelString { case "error", "warn", "info", "debug": default: - return fmt.Errorf("Invalid loglevel %s Must be one of [error, warn, info, debug]", loglevelString) + return fmt.Errorf("invalid loglevel %s Must be one of [error, warn, info, debug]", loglevelString) } *loglevel = Loglevel(loglevelString) @@ -463,7 +469,7 @@ } if len(types) > 1 { - return fmt.Errorf("Must provide exactly one storage type. Provided: %v", types) + return fmt.Errorf("must provide exactly one storage type. Provided: %v", types) } } *storage = storageMap @@ -665,11 +671,11 @@ v0_1.Loglevel = Loglevel("") } if v0_1.Storage.Type() == "" { - return nil, errors.New("No storage configuration provided") + return nil, errors.New("no storage configuration provided") } return (*Configuration)(v0_1), nil } - return nil, fmt.Errorf("Expected *v0_1Configuration, received %#v", c) + return nil, fmt.Errorf("expected *v0_1Configuration, received %#v", c) }, }, }) diff -Nru docker-registry-2.7.1+ds2/configuration/configuration_test.go docker-registry-2.8.0+ds1/configuration/configuration_test.go --- docker-registry-2.7.1+ds2/configuration/configuration_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/configuration/configuration_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -80,10 +80,12 @@ RelativeURLs bool `yaml:"relativeurls,omitempty"` DrainTimeout time.Duration `yaml:"draintimeout,omitempty"` TLS struct { - Certificate string `yaml:"certificate,omitempty"` - Key string `yaml:"key,omitempty"` - ClientCAs []string `yaml:"clientcas,omitempty"` - LetsEncrypt struct { + Certificate string `yaml:"certificate,omitempty"` + Key string `yaml:"key,omitempty"` + ClientCAs []string `yaml:"clientcas,omitempty"` + MinimumTLS string `yaml:"minimumtls,omitempty"` + CipherSuites []string `yaml:"ciphersuites,omitempty"` + LetsEncrypt struct { CacheFile string `yaml:"cachefile,omitempty"` Email string `yaml:"email,omitempty"` Hosts []string `yaml:"hosts,omitempty"` @@ -102,10 +104,12 @@ } `yaml:"http2,omitempty"` }{ TLS: struct { - Certificate string `yaml:"certificate,omitempty"` - Key string `yaml:"key,omitempty"` - ClientCAs []string `yaml:"clientcas,omitempty"` - LetsEncrypt struct { + Certificate string `yaml:"certificate,omitempty"` + Key string `yaml:"key,omitempty"` + ClientCAs []string `yaml:"clientcas,omitempty"` + MinimumTLS string `yaml:"minimumtls,omitempty"` + CipherSuites []string `yaml:"ciphersuites,omitempty"` + LetsEncrypt struct { CacheFile string `yaml:"cachefile,omitempty"` Email string `yaml:"email,omitempty"` Hosts []string `yaml:"hosts,omitempty"` @@ -540,9 +544,7 @@ } configCopy.Notifications = Notifications{Endpoints: []Endpoint{}} - for _, v := range config.Notifications.Endpoints { - configCopy.Notifications.Endpoints = append(configCopy.Notifications.Endpoints, v) - } + configCopy.Notifications.Endpoints = append(configCopy.Notifications.Endpoints, config.Notifications.Endpoints...) configCopy.HTTP.Headers = make(http.Header) for k, v := range config.HTTP.Headers { diff -Nru docker-registry-2.7.1+ds2/configuration/parser.go docker-registry-2.8.0+ds1/configuration/parser.go --- docker-registry-2.7.1+ds2/configuration/parser.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/configuration/parser.go 2022-02-07 15:40:21.000000000 +0000 @@ -122,7 +122,7 @@ parseInfo, ok := p.mapping[versionedStruct.Version] if !ok { - return fmt.Errorf("Unsupported version: %q", versionedStruct.Version) + return fmt.Errorf("unsupported version: %q", versionedStruct.Version) } parseAs := reflect.New(parseInfo.ParseAs) diff -Nru docker-registry-2.7.1+ds2/contrib/token-server/main.go docker-registry-2.8.0+ds1/contrib/token-server/main.go --- docker-registry-2.7.1+ds2/contrib/token-server/main.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/contrib/token-server/main.go 2022-02-07 15:40:21.000000000 +0000 @@ -2,9 +2,10 @@ import ( "context" + "crypto/rand" "encoding/json" "flag" - "math/rand" + "math/big" "net/http" "strconv" "strings" @@ -141,8 +142,15 @@ func newRefreshToken() string { s := make([]rune, refreshTokenLength) + max := int64(len(refreshCharacters)) for i := range s { - s[i] = refreshCharacters[rand.Intn(len(refreshCharacters))] + randInt, err := rand.Int(rand.Reader, big.NewInt(max)) + // let '0' serves the failure case + if err != nil { + logrus.Infof("Error on making refersh token: %v", err) + randInt = big.NewInt(0) + } + s[i] = refreshCharacters[randInt.Int64()] } return string(s) } diff -Nru docker-registry-2.7.1+ds2/debian/changelog docker-registry-2.8.0+ds1/debian/changelog --- docker-registry-2.7.1+ds2/debian/changelog 2020-11-11 22:07:21.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/changelog 2022-02-11 06:27:09.000000000 +0000 @@ -1,14 +1,34 @@ -docker-registry (2.7.1+ds2-7build2) hirsute; urgency=medium +docker-registry (2.8.0+ds1-4) unstable; urgency=medium - * No-change rebuild using new golang + * Team upload + * Skip failed tests + + Flaky: TestGracefulShutdown and TestRegistrySupportedCipherSuite + + Need network: TestRegistryAsCacheMutationAPIs - -- Steve Langasek Wed, 11 Nov 2020 22:07:21 +0000 + -- Shengjing Zhu Fri, 11 Feb 2022 14:27:09 +0800 -docker-registry (2.7.1+ds2-7build1) groovy; urgency=medium +docker-registry (2.8.0+ds1-3) unstable; urgency=medium - * No-change rebuild using new golang + * Team upload + * Upload to unstable + * Try to fix tests by increase timeout and sleep time - -- Steve Langasek Tue, 22 Sep 2020 08:49:20 +0000 + -- Shengjing Zhu Fri, 11 Feb 2022 02:11:51 +0800 + +docker-registry (2.8.0+ds1-2) experimental; urgency=medium + + * Team upload + * Increase test timeout as it timed out on mipsel + * Drop dh-exec + + -- Shengjing Zhu Wed, 09 Feb 2022 00:56:46 +0800 + +docker-registry (2.8.0+ds1-1) experimental; urgency=medium + + * Team upload + * New upstream release v2.8.0 + + -- Shengjing Zhu Tue, 08 Feb 2022 01:35:42 +0800 docker-registry (2.7.1+ds2-7) unstable; urgency=medium diff -Nru docker-registry-2.7.1+ds2/debian/clean docker-registry-2.8.0+ds1/debian/clean --- docker-registry-2.7.1+ds2/debian/clean 2019-12-16 05:31:51.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/clean 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -registry/storage/driver/azure/* diff -Nru docker-registry-2.7.1+ds2/debian/control docker-registry-2.8.0+ds1/debian/control --- docker-registry-2.7.1+ds2/debian/control 2020-09-22 08:49:20.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/control 2022-02-11 06:27:09.000000000 +0000 @@ -2,18 +2,16 @@ Section: utils Priority: optional Standards-Version: 4.4.1 -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Debian Go Packaging Team +Maintainer: Debian Go Packaging Team Uploaders: Arnaud Rebillout , Dmitry Smirnov , Tianon Gravi , Tim Potter , -Build-Depends: debhelper-compat (= 12), - dh-exec, +Build-Depends: debhelper-compat (= 13), dh-golang, golang-any, golang-github-aws-aws-sdk-go-dev, - golang-github-bshuster-repo-logrus-logstash-hook-dev (>= 0.4.1), + golang-github-bshuster-repo-logrus-logstash-hook-dev, golang-github-bugsnag-bugsnag-go-dev, golang-github-docker-go-metrics-dev, golang-github-docker-libtrust-dev, @@ -21,28 +19,30 @@ golang-github-gorilla-handlers-dev, golang-github-gorilla-mux-dev, golang-github-mitchellh-mapstructure-dev, - golang-github-ncw-swift-dev (>= 0.0~git20151108), + golang-github-ncw-swift-dev, golang-github-opencontainers-go-digest-dev, golang-github-opencontainers-image-spec-dev, golang-github-shopify-logrus-bugsnag-dev, - golang-github-sirupsen-logrus-dev (>= 1.0.2~), + golang-github-sirupsen-logrus-dev, golang-github-spf13-cobra-dev, golang-golang-x-crypto-dev, - golang-golang-x-net-dev, golang-gopkg-check.v1-dev, golang-gopkg-yaml.v2-dev, - golang-protobuf-extensions-dev, Homepage: https://github.com/docker/distribution Vcs-Browser: https://salsa.debian.org/go-team/packages/golang-github-docker-distribution Vcs-Git: https://salsa.debian.org/go-team/packages/golang-github-docker-distribution.git -XS-Go-Import-Path: github.com/docker/distribution +Rules-Requires-Root: no Testsuite: autopkgtest-pkg-go +XS-Go-Import-Path: github.com/docker/distribution Package: docker-registry Architecture: any -Depends: adduser, ${misc:Depends}, ${shlibs:Depends}, lsb-base -Pre-Depends: ${misc:Pre-Depends} -Built-Using: ${misc:Built-Using} +Depends: adduser, + lsb-base, + ${misc:Depends}, + ${shlibs:Depends}, +Pre-Depends: ${misc:Pre-Depends}, +Built-Using: ${misc:Built-Using}, Description: Docker toolset to pack, ship, store, and deliver content The Docker toolset to pack, ship, store, and deliver content. . @@ -64,8 +64,7 @@ Package: golang-github-docker-distribution-dev Architecture: all -Depends: ${misc:Depends}, - golang-github-aws-aws-sdk-go-dev, +Depends: golang-github-aws-aws-sdk-go-dev, golang-github-bugsnag-bugsnag-go-dev, golang-github-docker-go-metrics-dev, golang-github-docker-libtrust-dev, @@ -76,12 +75,11 @@ golang-github-ncw-swift-dev, golang-github-opencontainers-go-digest-dev, golang-github-opencontainers-image-spec-dev, - golang-github-sirupsen-logrus-dev (>= 1.0.2~), + golang-github-sirupsen-logrus-dev, golang-github-spf13-cobra-dev, golang-golang-x-crypto-dev, - golang-golang-x-net-dev, - golang-gopkg-check.v1-dev, golang-gopkg-yaml.v2-dev, + ${misc:Depends}, Description: Docker toolset to pack, ship, store, and deliver content (source) The Docker toolset to pack, ship, store, and deliver content. . diff -Nru docker-registry-2.7.1+ds2/debian/copyright docker-registry-2.8.0+ds1/debian/copyright --- docker-registry-2.7.1+ds2/debian/copyright 2019-12-16 05:31:51.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/copyright 2022-02-11 06:27:09.000000000 +0000 @@ -12,6 +12,10 @@ License: Apache-2.0 Comment: Debian packaging is licensed under the same terms as upstream +Files: registry/storage/driver/s3-aws/s3_v2_signer.go +Copyright: 2013 Damien Le Berrigaud and Nick Wade +License: Expat + License: Apache-2.0 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -27,3 +31,22 @@ . On Debian systems, the complete text of the Apache version 2.0 license can be found in "/usr/share/common-licenses/Apache-2.0". + +License: Expat + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff -Nru docker-registry-2.7.1+ds2/debian/docker-registry.docs docker-registry-2.8.0+ds1/debian/docker-registry.docs --- docker-registry-2.7.1+ds2/debian/docker-registry.docs 2019-12-16 05:31:51.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/docker-registry.docs 2022-02-11 06:27:09.000000000 +0000 @@ -1,3 +1,4 @@ +README.md +docs/architecture.md +docs/configuration.md docs/spec -docs/*.md -README* diff -Nru docker-registry-2.7.1+ds2/debian/docker-registry.install docker-registry-2.8.0+ds1/debian/docker-registry.install --- docker-registry-2.7.1+ds2/debian/docker-registry.install 2019-12-16 05:31:51.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/docker-registry.install 2022-02-11 06:27:09.000000000 +0000 @@ -1,3 +1,2 @@ -#!/usr/bin/dh-exec -usr/bin/registry => usr/bin/docker-registry -cmd/registry/config-example.yml => etc/docker/registry/config.yml +usr/bin/ +etc/ diff -Nru docker-registry-2.7.1+ds2/debian/gbp.conf docker-registry-2.8.0+ds1/debian/gbp.conf --- docker-registry-2.7.1+ds2/debian/gbp.conf 2019-12-16 05:31:51.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/gbp.conf 2022-02-11 06:27:09.000000000 +0000 @@ -1,11 +1,2 @@ -[buildpackage] -overlay = True -export-dir = ../build-area/ -tarball-dir = ../ - -[dch] -id-length = 0 - -[import-orig] +[DEFAULT] pristine-tar = True -merge = False diff -Nru docker-registry-2.7.1+ds2/debian/gitlab-ci.yml docker-registry-2.8.0+ds1/debian/gitlab-ci.yml --- docker-registry-2.7.1+ds2/debian/gitlab-ci.yml 2019-12-16 05:31:51.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/gitlab-ci.yml 2022-02-11 06:27:09.000000000 +0000 @@ -1,28 +1,6 @@ - # auto-generated, DO NOT MODIFY. # The authoritative copy of this file lives at: -# https://salsa.debian.org/go-team/ci/blob/master/cmd/ci/gitlabciyml.go - -# TODO: publish under debian-go-team/ci -image: stapelberg/ci2 - -test_the_archive: - artifacts: - paths: - - before-applying-commit.json - - after-applying-commit.json - script: - # Create an overlay to discard writes to /srv/gopath/src after the build: - - "rm -rf /cache/overlay/{upper,work}" - - "mkdir -p /cache/overlay/{upper,work}" - - "mount -t overlay overlay -o lowerdir=/srv/gopath/src,upperdir=/cache/overlay/upper,workdir=/cache/overlay/work /srv/gopath/src" - - "export GOPATH=/srv/gopath" - - "export GOCACHE=/cache/go" - # Build the world as-is: - - "ci-build -exemptions=/var/lib/ci-build/exemptions.json > before-applying-commit.json" - # Copy this package into the overlay: - - "GBP_CONF_FILES=:debian/gbp.conf gbp buildpackage --git-no-pristine-tar --git-ignore-branch --git-ignore-new --git-export-dir=/tmp/export --git-no-overlay --git-tarball-dir=/nonexistant --git-cleaner=/bin/true --git-builder='dpkg-buildpackage -S -d --no-sign'" - - "pgt-gopath -dsc /tmp/export/*.dsc" - # Rebuild the world: - - "ci-build -exemptions=/var/lib/ci-build/exemptions.json > after-applying-commit.json" - - "ci-diff before-applying-commit.json after-applying-commit.json" +# https://salsa.debian.org/go-team/infra/pkg-go-tools/blob/master/config/gitlabciyml.go +--- +include: + - https://salsa.debian.org/go-team/infra/pkg-go-tools/-/raw/master/pipeline/test-archive.yml diff -Nru docker-registry-2.7.1+ds2/debian/patches/0001-config-allow-delete.patch docker-registry-2.8.0+ds1/debian/patches/0001-config-allow-delete.patch --- docker-registry-2.7.1+ds2/debian/patches/0001-config-allow-delete.patch 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/0001-config-allow-delete.patch 2022-02-11 06:27:09.000000000 +0000 @@ -0,0 +1,23 @@ +From: Dmitry Smirnov +Date: Tue, 8 Feb 2022 00:39:58 +0800 +Subject: allow delete by default. + +Last-Update: 2016-08-18 +Forwarded: not-needed +--- + cmd/registry/config-example.yml | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/cmd/registry/config-example.yml b/cmd/registry/config-example.yml +index c760cd5..a05cb1a 100644 +--- a/cmd/registry/config-example.yml ++++ b/cmd/registry/config-example.yml +@@ -7,6 +7,8 @@ storage: + blobdescriptor: inmemory + filesystem: + rootdirectory: /var/lib/registry ++ delete: ++ enabled: true + http: + addr: :5000 + headers: diff -Nru docker-registry-2.7.1+ds2/debian/patches/0002-config-docker-registry.patch docker-registry-2.8.0+ds1/debian/patches/0002-config-docker-registry.patch --- docker-registry-2.7.1+ds2/debian/patches/0002-config-docker-registry.patch 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/0002-config-docker-registry.patch 2022-02-11 06:27:09.000000000 +0000 @@ -0,0 +1,45 @@ +From: Tianon Gravi +Date: Tue, 8 Feb 2022 00:39:58 +0800 +Subject: Patch the default "rootdirectory" for policy compliance + +Forwarded: no +--- + cmd/registry/config-dev.yml | 2 +- + cmd/registry/config-example.yml | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/cmd/registry/config-dev.yml b/cmd/registry/config-dev.yml +index 9539bae..8869908 100644 +--- a/cmd/registry/config-dev.yml ++++ b/cmd/registry/config-dev.yml +@@ -24,7 +24,7 @@ storage: + cache: + blobdescriptor: redis + filesystem: +- rootdirectory: /var/lib/registry ++ rootdirectory: /var/lib/docker-registry + maintenance: + uploadpurging: + enabled: false +diff --git a/cmd/registry/config-example.yml b/cmd/registry/config-example.yml +index a05cb1a..d2aecbb 100644 +--- a/cmd/registry/config-example.yml ++++ b/cmd/registry/config-example.yml +@@ -6,7 +6,7 @@ storage: + cache: + blobdescriptor: inmemory + filesystem: +- rootdirectory: /var/lib/registry ++ rootdirectory: /var/lib/docker-registry + delete: + enabled: true + http: +@@ -16,7 +16,7 @@ http: + auth: + htpasswd: + realm: basic-realm +- path: /etc/registry ++ path: /etc/docker/registry + health: + storagedriver: + enabled: true diff -Nru docker-registry-2.7.1+ds2/debian/patches/0003-no-azure.patch docker-registry-2.8.0+ds1/debian/patches/0003-no-azure.patch --- docker-registry-2.7.1+ds2/debian/patches/0003-no-azure.patch 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/0003-no-azure.patch 2022-02-11 06:27:09.000000000 +0000 @@ -0,0 +1,22 @@ +From: Dmitry Smirnov +Date: Tue, 8 Feb 2022 00:39:58 +0800 +Subject: removed Azure support + +Last-Update: 2019-12-07 +Forwarded: not-needed +--- + cmd/registry/main.go | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/cmd/registry/main.go b/cmd/registry/main.go +index 5beaa56..a868839 100644 +--- a/cmd/registry/main.go ++++ b/cmd/registry/main.go +@@ -8,7 +8,6 @@ import ( + _ "github.com/docker/distribution/registry/auth/silly" + _ "github.com/docker/distribution/registry/auth/token" + _ "github.com/docker/distribution/registry/proxy" +- _ "github.com/docker/distribution/registry/storage/driver/azure" + _ "github.com/docker/distribution/registry/storage/driver/filesystem" + _ "github.com/docker/distribution/registry/storage/driver/gcs" + _ "github.com/docker/distribution/registry/storage/driver/inmemory" diff -Nru docker-registry-2.7.1+ds2/debian/patches/0004-replace-rsc.io-letsencrypt-in-favour-of-golang.org-x.patch docker-registry-2.8.0+ds1/debian/patches/0004-replace-rsc.io-letsencrypt-in-favour-of-golang.org-x.patch --- docker-registry-2.7.1+ds2/debian/patches/0004-replace-rsc.io-letsencrypt-in-favour-of-golang.org-x.patch 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/0004-replace-rsc.io-letsencrypt-in-favour-of-golang.org-x.patch 2022-02-11 06:27:09.000000000 +0000 @@ -0,0 +1,65 @@ +From: Tariq Ibrahim +Date: Tue, 8 Feb 2022 00:48:18 +0800 +Subject: replace rsc.io/letsencrypt in favour of golang.org/x/crypto + +Origin: backport, https://github.com/distribution/distribution/pull/2926 +--- + registry/registry.go | 22 +++++++++------------- + 1 file changed, 9 insertions(+), 13 deletions(-) + +diff --git a/registry/registry.go b/registry/registry.go +index dc156f4..1fc2edd 100644 +--- a/registry/registry.go ++++ b/registry/registry.go +@@ -13,7 +13,8 @@ import ( + "syscall" + "time" + +- "rsc.io/letsencrypt" ++ "golang.org/x/crypto/acme" ++ "golang.org/x/crypto/acme/autocert" + + logrus_bugsnag "github.com/Shopify/logrus-bugsnag" + +@@ -79,6 +80,7 @@ var defaultCipherSuites = []uint16{ + + // maps tls version strings to constants + var defaultTLSVersionStr = "tls1.2" ++ + var tlsVersions = map[string]uint16{ + // user specified values + "tls1.0": tls.VersionTLS10, +@@ -96,7 +98,6 @@ var ServeCmd = &cobra.Command{ + Short: "`serve` stores and distributes Docker images", + Long: "`serve` stores and distributes Docker images.", + Run: func(cmd *cobra.Command, args []string) { +- + // setup context + ctx := dcontext.WithVersion(dcontext.Background(), version.Version) + +@@ -247,19 +248,14 @@ func (registry *Registry) ListenAndServe() error { + if config.HTTP.TLS.Certificate != "" { + return fmt.Errorf("cannot specify both certificate and Let's Encrypt") + } +- var m letsencrypt.Manager +- if err := m.CacheFile(config.HTTP.TLS.LetsEncrypt.CacheFile); err != nil { +- return err +- } +- if !m.Registered() { +- if err := m.Register(config.HTTP.TLS.LetsEncrypt.Email, nil); err != nil { +- return err +- } +- } +- if len(config.HTTP.TLS.LetsEncrypt.Hosts) > 0 { +- m.SetHosts(config.HTTP.TLS.LetsEncrypt.Hosts) ++ m := &autocert.Manager{ ++ HostPolicy: autocert.HostWhitelist(config.HTTP.TLS.LetsEncrypt.Hosts...), ++ Cache: autocert.DirCache(config.HTTP.TLS.LetsEncrypt.CacheFile), ++ Email: config.HTTP.TLS.LetsEncrypt.Email, ++ Prompt: autocert.AcceptTOS, + } + tlsConf.GetCertificate = m.GetCertificate ++ tlsConf.NextProtos = append(tlsConf.NextProtos, acme.ALPNProto) + } else { + tlsConf.Certificates = make([]tls.Certificate, 1) + tlsConf.Certificates[0], err = tls.LoadX509KeyPair(config.HTTP.TLS.Certificate, config.HTTP.TLS.Key) diff -Nru docker-registry-2.7.1+ds2/debian/patches/0005-Temporarily-remove-newrelic-support-to-cut-down-on-d.patch docker-registry-2.8.0+ds1/debian/patches/0005-Temporarily-remove-newrelic-support-to-cut-down-on-d.patch --- docker-registry-2.7.1+ds2/debian/patches/0005-Temporarily-remove-newrelic-support-to-cut-down-on-d.patch 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/0005-Temporarily-remove-newrelic-support-to-cut-down-on-d.patch 2022-02-11 06:27:09.000000000 +0000 @@ -0,0 +1,40 @@ +From: Tianon Gravi +Date: Tue, 8 Feb 2022 00:50:36 +0800 +Subject: Temporarily remove newrelic support to cut down on dependencies for + initial release + +Forwarded: not-needed +--- + registry/registry.go | 12 +----------- + 1 file changed, 1 insertion(+), 11 deletions(-) + +diff --git a/registry/registry.go b/registry/registry.go +index 1fc2edd..0617027 100644 +--- a/registry/registry.go ++++ b/registry/registry.go +@@ -31,7 +31,6 @@ import ( + gorhandlers "github.com/gorilla/handlers" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +- "github.com/yvasiyarov/gorelic" + ) + + // a map of TLS cipher suite names to constants in https://golang.org/pkg/crypto/tls/#pkg-constants +@@ -325,16 +324,7 @@ func configureReporting(app *handlers.App) http.Handler { + } + + if app.Config.Reporting.NewRelic.LicenseKey != "" { +- agent := gorelic.NewAgent() +- agent.NewrelicLicense = app.Config.Reporting.NewRelic.LicenseKey +- if app.Config.Reporting.NewRelic.Name != "" { +- agent.NewrelicName = app.Config.Reporting.NewRelic.Name +- } +- agent.CollectHTTPStat = true +- agent.Verbose = app.Config.Reporting.NewRelic.Verbose +- agent.Run() +- +- handler = agent.WrapHTTPHandler(handler) ++ log.Warnf("NewRelic LicenseKey provided, but this install does not include NewRelic support") + } + + return handler diff -Nru docker-registry-2.7.1+ds2/debian/patches/0006-Skip-TestHTTPChecker.patch docker-registry-2.8.0+ds1/debian/patches/0006-Skip-TestHTTPChecker.patch --- docker-registry-2.7.1+ds2/debian/patches/0006-Skip-TestHTTPChecker.patch 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/0006-Skip-TestHTTPChecker.patch 2022-02-11 06:27:09.000000000 +0000 @@ -0,0 +1,21 @@ +From: Shengjing Zhu +Date: Tue, 8 Feb 2022 01:07:49 +0800 +Subject: Skip TestHTTPChecker + +Forwarded: not-needed +--- + health/checks/checks_test.go | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/health/checks/checks_test.go b/health/checks/checks_test.go +index 6b6dd14..d803990 100644 +--- a/health/checks/checks_test.go ++++ b/health/checks/checks_test.go +@@ -15,6 +15,7 @@ func TestFileChecker(t *testing.T) { + } + + func TestHTTPChecker(t *testing.T) { ++ t.Skip("No network access in Debian buildd") + if err := HTTPChecker("https://www.google.cybertron", 200, 0, nil).Check(); err == nil { + t.Errorf("Google on Cybertron was expected as not exists") + } diff -Nru docker-registry-2.7.1+ds2/debian/patches/0007-Skip-TestRegistryAsCacheMutationAPIs.patch docker-registry-2.8.0+ds1/debian/patches/0007-Skip-TestRegistryAsCacheMutationAPIs.patch --- docker-registry-2.7.1+ds2/debian/patches/0007-Skip-TestRegistryAsCacheMutationAPIs.patch 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/0007-Skip-TestRegistryAsCacheMutationAPIs.patch 2022-02-11 06:27:09.000000000 +0000 @@ -0,0 +1,25 @@ +From: Shengjing Zhu +Date: Fri, 11 Feb 2022 03:16:24 +0800 +Subject: Skip TestRegistryAsCacheMutationAPIs + +FAIL: TestRegistryAsCacheMutationAPIs (0.09s) +panic: Get "http://example.com/v2/": dial tcp: lookup example.com: Temporary failure in name resolution [recovered] + panic: Get "http://example.com/v2/": dial tcp: lookup example.com: Temporary failure in name resolution + +Forwarded: not-needed +--- + registry/handlers/api_test.go | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/registry/handlers/api_test.go b/registry/handlers/api_test.go +index 2d3edc7..a07184b 100644 +--- a/registry/handlers/api_test.go ++++ b/registry/handlers/api_test.go +@@ -2468,6 +2468,7 @@ func createRepository(env *testEnv, t *testing.T, imageName string, tag string) + // Test mutation operations on a registry configured as a cache. Ensure that they return + // appropriate errors. + func TestRegistryAsCacheMutationAPIs(t *testing.T) { ++ t.Skip("No network access in Debian buildd") + deleteEnabled := true + env := newTestEnvMirror(t, deleteEnabled) + defer env.Shutdown() diff -Nru docker-registry-2.7.1+ds2/debian/patches/0008-Skip-flaky-TestGracefulShutdown-and-TestRegistrySupp.patch docker-registry-2.8.0+ds1/debian/patches/0008-Skip-flaky-TestGracefulShutdown-and-TestRegistrySupp.patch --- docker-registry-2.7.1+ds2/debian/patches/0008-Skip-flaky-TestGracefulShutdown-and-TestRegistrySupp.patch 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/0008-Skip-flaky-TestGracefulShutdown-and-TestRegistrySupp.patch 2022-02-11 06:27:09.000000000 +0000 @@ -0,0 +1,37 @@ +From: Shengjing Zhu +Date: Fri, 11 Feb 2022 02:07:08 +0800 +Subject: Skip flaky TestGracefulShutdown and TestRegistrySupportedCipherSuite + +On debci.d.n + +registry_test.go:109: Managed to connect after stopping +FAIL: TestGracefulShutdown + +registry_test.go:286: dial tcp 127.0.0.1:5001: connect: connection refused +FAIL: TestRegistrySupportedCipherSuite + +Forwarded: not-needed +--- + registry/registry_test.go | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/registry/registry_test.go b/registry/registry_test.go +index c7eb85e..cfcdc1e 100644 +--- a/registry/registry_test.go ++++ b/registry/registry_test.go +@@ -73,6 +73,7 @@ func setupRegistry(tlsCfg *registryTLSConfig, addr string) (*Registry, error) { + } + + func TestGracefulShutdown(t *testing.T) { ++ t.Skip("flaky") + registry, err := setupRegistry(nil, ":5000") + if err != nil { + t.Fatal(err) +@@ -243,6 +244,7 @@ func buildRegistryTLSConfig(name, keyType string, cipherSuites []string) (*regis + } + + func TestRegistrySupportedCipherSuite(t *testing.T) { ++ t.Skip("flaky") + name := "registry_test_server_supported_cipher" + cipherSuites := []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"} + serverTLS, err := buildRegistryTLSConfig(name, "rsa", cipherSuites) diff -Nru docker-registry-2.7.1+ds2/debian/patches/config-allow-delete.patch docker-registry-2.8.0+ds1/debian/patches/config-allow-delete.patch --- docker-registry-2.7.1+ds2/debian/patches/config-allow-delete.patch 2019-12-16 05:31:51.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/config-allow-delete.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -Last-Update: 2016-08-18 -Forwarded: not-needed -Author: Dmitry Smirnov -Description: allow delete by default. - ---- a/cmd/registry/config-example.yml -+++ b/cmd/registry/config-example.yml -@@ -6,8 +6,10 @@ - cache: - blobdescriptor: inmemory - filesystem: - rootdirectory: /var/lib/registry -+ delete: -+ enabled: true - http: - addr: :5000 - headers: - X-Content-Type-Options: [nosniff] diff -Nru docker-registry-2.7.1+ds2/debian/patches/config-docker-registry.patch docker-registry-2.8.0+ds1/debian/patches/config-docker-registry.patch --- docker-registry-2.7.1+ds2/debian/patches/config-docker-registry.patch 2020-01-06 04:41:01.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/config-docker-registry.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -Description: Patch the default "rootdirectory" for policy compliance -Author: Tianon Gravi -Forwarded: no - ---- a/cmd/registry/config-example.yml -+++ b/cmd/registry/config-example.yml -@@ -5,9 +5,9 @@ - storage: - cache: - blobdescriptor: inmemory - filesystem: -- rootdirectory: /var/lib/registry -+ rootdirectory: /var/lib/docker-registry - delete: - enabled: true - http: - addr: :5000 -@@ -15,9 +15,9 @@ - X-Content-Type-Options: [nosniff] - auth: - htpasswd: - realm: basic-realm -- path: /etc/registry -+ path: /etc/docker/registry - health: - storagedriver: - enabled: true - interval: 10s ---- a/cmd/registry/config-dev.yml -+++ b/cmd/registry/config-dev.yml -@@ -23,9 +23,9 @@ - enabled: true - cache: - blobdescriptor: redis - filesystem: -- rootdirectory: /var/lib/registry -+ rootdirectory: /var/lib/docker-registry - maintenance: - uploadpurging: - enabled: false - http: diff -Nru docker-registry-2.7.1+ds2/debian/patches/lib-crypto.patch docker-registry-2.8.0+ds1/debian/patches/lib-crypto.patch --- docker-registry-2.7.1+ds2/debian/patches/lib-crypto.patch 2020-01-07 07:49:01.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/lib-crypto.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -From: Tariq Ibrahim -Date: Wed, 15 May 2019 17:21:50 -0700 -Subject: replace rsc.io/letsencrypt in favour of golang.org/x/crypto - -Signed-off-by: Tariq Ibrahim -Origin: upstream, https://github.com/docker/distribution/pull/2926/commits/8f9c8094fbe639e6b4e56e5c574932e629b145ef - -diff --git a/registry/registry.go b/registry/registry.go -index 03ff3fd7..e4fe36cb 10064 ---- a/registry/registry.go -+++ b/registry/registry.go -@@ -12,11 +12,17 @@ import ( - "syscall" - "time" - -- "rsc.io/letsencrypt" -- - "github.com/Shopify/logrus-bugsnag" - logstash "github.com/bshuster-repo/logrus-logstash-hook" - "github.com/bugsnag/bugsnag-go" -+ "github.com/docker/go-metrics" -+ gorhandlers "github.com/gorilla/handlers" -+ log "github.com/sirupsen/logrus" -+ "github.com/spf13/cobra" -+ "github.com/yvasiyarov/gorelic" -+ "golang.org/x/crypto/acme" -+ "golang.org/x/crypto/acme/autocert" -+ - "github.com/docker/distribution/configuration" - dcontext "github.com/docker/distribution/context" - "github.com/docker/distribution/health" -@@ -24,11 +30,6 @@ import ( - "github.com/docker/distribution/registry/listener" - "github.com/docker/distribution/uuid" - "github.com/docker/distribution/version" -- "github.com/docker/go-metrics" -- gorhandlers "github.com/gorilla/handlers" -- log "github.com/sirupsen/logrus" -- "github.com/spf13/cobra" -- "github.com/yvasiyarov/gorelic" - ) - - // this channel gets notified when process receives signal. It is global to ease unit testing -@@ -154,19 +155,14 @@ func (registry *Registry) ListenAndServe() error { - if config.HTTP.TLS.Certificate != "" { - return fmt.Errorf("cannot specify both certificate and Let's Encrypt") - } -- var m letsencrypt.Manager -- if err := m.CacheFile(config.HTTP.TLS.LetsEncrypt.CacheFile); err != nil { -- return err -- } -- if !m.Registered() { -- if err := m.Register(config.HTTP.TLS.LetsEncrypt.Email, nil); err != nil { -- return err -- } -- } -- if len(config.HTTP.TLS.LetsEncrypt.Hosts) > 0 { -- m.SetHosts(config.HTTP.TLS.LetsEncrypt.Hosts) -+ m := &autocert.Manager{ -+ HostPolicy: autocert.HostWhitelist(config.HTTP.TLS.LetsEncrypt.Hosts...), -+ Cache: autocert.DirCache(config.HTTP.TLS.LetsEncrypt.CacheFile), -+ Email: config.HTTP.TLS.LetsEncrypt.Email, -+ Prompt: autocert.AcceptTOS, - } - tlsConf.GetCertificate = m.GetCertificate -+ tlsConf.NextProtos = append(tlsConf.NextProtos, acme.ALPNProto) - } else { - tlsConf.Certificates = make([]tls.Certificate, 1) - tlsConf.Certificates[0], err = tls.LoadX509KeyPair(config.HTTP.TLS.Certificate, config.HTTP.TLS.Key) diff -Nru docker-registry-2.7.1+ds2/debian/patches/no-azure.patch docker-registry-2.8.0+ds1/debian/patches/no-azure.patch --- docker-registry-2.7.1+ds2/debian/patches/no-azure.patch 2019-12-16 05:31:51.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/no-azure.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -Last-Update: 2019-12-07 -Forwarded: not-needed -Author: Dmitry Smirnov -Description: removed Azure support - ---- a/cmd/registry/main.go -+++ b/cmd/registry/main.go -@@ -7,9 +7,8 @@ - _ "github.com/docker/distribution/registry/auth/htpasswd" - _ "github.com/docker/distribution/registry/auth/silly" - _ "github.com/docker/distribution/registry/auth/token" - _ "github.com/docker/distribution/registry/proxy" -- _ "github.com/docker/distribution/registry/storage/driver/azure" - _ "github.com/docker/distribution/registry/storage/driver/filesystem" - _ "github.com/docker/distribution/registry/storage/driver/gcs" - _ "github.com/docker/distribution/registry/storage/driver/inmemory" - _ "github.com/docker/distribution/registry/storage/driver/middleware/cloudfront" diff -Nru docker-registry-2.7.1+ds2/debian/patches/no-relic.patch docker-registry-2.8.0+ds1/debian/patches/no-relic.patch --- docker-registry-2.7.1+ds2/debian/patches/no-relic.patch 2020-01-07 07:39:54.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/no-relic.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -Description: Temporarily remove newrelic support to cut down on dependencies for initial release -Author: Tianon Gravi -Forwarded: not-needed - ---- a/registry/registry.go -+++ b/registry/registry.go -@@ -19,7 +19,6 @@ import ( - gorhandlers "github.com/gorilla/handlers" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -- "github.com/yvasiyarov/gorelic" - "golang.org/x/crypto/acme" - "golang.org/x/crypto/acme/autocert" - -@@ -232,16 +231,7 @@ func configureReporting(app *handlers.Ap - } - - if app.Config.Reporting.NewRelic.LicenseKey != "" { -- agent := gorelic.NewAgent() -- agent.NewrelicLicense = app.Config.Reporting.NewRelic.LicenseKey -- if app.Config.Reporting.NewRelic.Name != "" { -- agent.NewrelicName = app.Config.Reporting.NewRelic.Name -- } -- agent.CollectHTTPStat = true -- agent.Verbose = app.Config.Reporting.NewRelic.Verbose -- agent.Run() -- -- handler = agent.WrapHTTPHandler(handler) -+ log.Warnf("NewRelic LicenseKey provided, but this install does not include NewRelic support") - } - - return handler diff -Nru docker-registry-2.7.1+ds2/debian/patches/series docker-registry-2.8.0+ds1/debian/patches/series --- docker-registry-2.7.1+ds2/debian/patches/series 2020-01-07 07:38:34.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/series 2022-02-11 06:27:09.000000000 +0000 @@ -1,6 +1,8 @@ -config-allow-delete.patch -config-docker-registry.patch -lib-crypto.patch -no-azure.patch -no-relic.patch -test.patch +0001-config-allow-delete.patch +0002-config-docker-registry.patch +0003-no-azure.patch +0004-replace-rsc.io-letsencrypt-in-favour-of-golang.org-x.patch +0005-Temporarily-remove-newrelic-support-to-cut-down-on-d.patch +0006-Skip-TestHTTPChecker.patch +0007-Skip-TestRegistryAsCacheMutationAPIs.patch +0008-Skip-flaky-TestGracefulShutdown-and-TestRegistrySupp.patch diff -Nru docker-registry-2.7.1+ds2/debian/patches/test.patch docker-registry-2.8.0+ds1/debian/patches/test.patch --- docker-registry-2.7.1+ds2/debian/patches/test.patch 2020-01-07 07:39:05.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/patches/test.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ ---- a/configuration/configuration_test.go -+++ b/configuration/configuration_test.go -@@ -212,12 +212,12 @@ func (suite *ConfigSuite) SetUpTest(c *C - // TestMarshalRoundtrip validates that configStruct can be marshaled and - // unmarshaled without changing any parameters - func (suite *ConfigSuite) TestMarshalRoundtrip(c *C) { -- configBytes, err := yaml.Marshal(suite.expectedConfig) -- c.Assert(err, IsNil) -- config, err := Parse(bytes.NewReader(configBytes)) -- c.Log(string(configBytes)) -- c.Assert(err, IsNil) -- c.Assert(config, DeepEquals, suite.expectedConfig) -+// configBytes, err := yaml.Marshal(suite.expectedConfig) -+// c.Assert(err, IsNil) -+// config, err := Parse(bytes.NewReader(configBytes)) -+// c.Log(string(configBytes)) -+// c.Assert(err, IsNil) -+// c.Assert(config, DeepEquals, suite.expectedConfig) - } - - // TestParseSimple validates that configYamlV0_1 can be parsed into a struct diff -Nru docker-registry-2.7.1+ds2/debian/rules docker-registry-2.8.0+ds1/debian/rules --- docker-registry-2.7.1+ds2/debian/rules 2019-12-16 05:31:51.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/rules 2022-02-11 06:27:09.000000000 +0000 @@ -1,21 +1,22 @@ #!/usr/bin/make -f -export DH_GOLANG_GO_GENERATE := 1 - include /usr/share/dpkg/pkg-info.mk -override_dh_clean: - dh_clean - ## Remove Files-Excluded (when built from checkout or non-DFSG tarball): - $(RM) -rv `perl -0nE 'say $$1 if m{^Files\-Excluded\:\s*(.*?)(?:\n\n|Files:|Comment:)}sm;' debian/copyright` - -find vendor -type d -empty -delete -print +export DH_GOLANG_EXCLUDES := \ + registry/storage/driver/azure \ + cmd/digest cmd/registry-api-descriptor-template \ + contrib/token-server + +%: + dh $@ --buildsystem=golang --with=golang override_dh_auto_build: dh_auto_build -- -ldflags '-X github.com/docker/distribution/version.Version=$(DEB_VERSION_UPSTREAM)' -override_dh_auto_test: - # health/checks hit the internet, and thus fail - #DH_GOLANG_EXCLUDES='distribution/registry/handlers health/checks' dh_auto_test -- -test.short +execute_after_dh_auto_install: + mv debian/tmp/usr/bin/registry debian/tmp/usr/bin/docker-registry + mkdir -p debian/tmp/etc/docker/registry + cp cmd/registry/config-example.yml debian/tmp/etc/docker/registry/config.yml -%: - dh $@ --buildsystem=golang --with=golang +override_dh_auto_test: + dh_auto_test -- -test.short -test.timeout=1h diff -Nru docker-registry-2.7.1+ds2/debian/TODO docker-registry-2.8.0+ds1/debian/TODO --- docker-registry-2.7.1+ds2/debian/TODO 2019-12-16 05:31:51.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/TODO 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -"TestRestoreOld" test failure on [armhf]: - - https://github.com/docker/distribution/issues/1927 diff -Nru docker-registry-2.7.1+ds2/debian/watch docker-registry-2.8.0+ds1/debian/watch --- docker-registry-2.7.1+ds2/debian/watch 2019-12-16 05:31:51.000000000 +0000 +++ docker-registry-2.8.0+ds1/debian/watch 2022-02-11 06:27:09.000000000 +0000 @@ -1,6 +1,7 @@ -version=3 -opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/docker-registry-$1\.tar\.gz/,\ -uversionmangle=s/(\d)[_\.\-\+]?(RC|rc|pre|dev|beta|alpha)[.]?(\d*)$/$1~$2$3/,\ -dversionmangle=s/[~+]ds\d*$//,\ -repacksuffix=+ds2 \ - https://github.com/docker/distribution/tags .*/v?(\d\S*)\.tar\.gz +version=4 +opts="filenamemangle=s%(?:.*?)?v?(@ANY_VERSION@@ARCHIVE_EXT@)%@PACKAGE@-$1%, \ + uversionmangle=s%(\d)-(rc|beta|alpha)\.?(\d*)$%$1~$2$3%, \ + dversionmangle=auto, \ + repacksuffix=+ds1" \ +https://github.com/distribution/distribution/tags \ +(?:.*?/)?v?@ANY_VERSION@\.tar\.gz diff -Nru docker-registry-2.7.1+ds2/docker-bake.hcl docker-registry-2.8.0+ds1/docker-bake.hcl --- docker-registry-2.7.1+ds2/docker-bake.hcl 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/docker-bake.hcl 2022-02-07 15:40:21.000000000 +0000 @@ -0,0 +1,51 @@ +group "default" { + targets = ["image-local"] +} + +// Special target: https://github.com/docker/metadata-action#bake-definition +target "docker-metadata-action" { + tags = ["registry:local"] +} + +target "binary" { + target = "binary" + output = ["./bin"] +} + +target "artifact" { + target = "artifacts" + output = ["./bin"] +} + +target "artifact-all" { + inherits = ["artifact"] + platforms = [ + "linux/amd64", + "linux/arm/v6", + "linux/arm/v7", + "linux/arm64", + "linux/ppc64le", + "linux/s390x" + ] +} + +target "image" { + inherits = ["docker-metadata-action"] +} + +target "image-local" { + inherits = ["image"] + output = ["type=docker"] +} + +target "image-all" { + inherits = ["image"] + platforms = [ + "linux/amd64", + "linux/arm/v6", + "linux/arm/v7", + "linux/arm64", + "linux/ppc64le", + "linux/s390x" + ] +} diff -Nru docker-registry-2.7.1+ds2/Dockerfile docker-registry-2.8.0+ds1/Dockerfile --- docker-registry-2.7.1+ds2/Dockerfile 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/Dockerfile 2022-02-07 15:40:21.000000000 +0000 @@ -1,22 +1,45 @@ -FROM golang:1.11-alpine AS build +# syntax=docker/dockerfile:1.3 -ENV DISTRIBUTION_DIR /go/src/github.com/docker/distribution -ENV BUILDTAGS include_oss include_gcs +ARG GO_VERSION=1.16 +ARG GORELEASER_XX_VERSION=1.2.5 -ARG GOOS=linux -ARG GOARCH=amd64 -ARG GOARM=6 +FROM --platform=$BUILDPLATFORM crazymax/goreleaser-xx:${GORELEASER_XX_VERSION} AS goreleaser-xx +FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS base +COPY --from=goreleaser-xx / / +RUN apk add --no-cache file git +WORKDIR /go/src/github.com/docker/distribution -RUN set -ex \ - && apk add --no-cache make git file +FROM base AS build +ENV GO111MODULE=auto +ENV CGO_ENABLED=0 +ARG TARGETPLATFORM +ARG PKG="github.com/distribution/distribution" +ARG BUILDTAGS="include_oss include_gcs" +RUN --mount=type=bind,rw \ + --mount=type=cache,target=/root/.cache/go-build \ + --mount=target=/go/pkg/mod,type=cache \ + goreleaser-xx --debug \ + --name="registry" \ + --dist="/out" \ + --main="./cmd/registry" \ + --flags="-v" \ + --ldflags="-s -w -X '$PKG/version.Version={{.Version}}' -X '$PKG/version.Revision={{.Commit}}' -X '$PKG/version.Package=$PKG'" \ + --tags="$BUILDTAGS" \ + --files="LICENSE" \ + --files="README.md" -WORKDIR $DISTRIBUTION_DIR -COPY . $DISTRIBUTION_DIR -RUN CGO_ENABLED=0 make PREFIX=/go clean binaries && file ./bin/registry | grep "statically linked" +FROM scratch AS artifacts +COPY --from=build /out/*.tar.gz / +COPY --from=build /out/*.zip / +COPY --from=build /out/*.sha256 / -FROM alpine +FROM scratch AS binary +COPY --from=build /usr/local/bin/registry* / + +FROM alpine:3.14 +RUN apk add --no-cache ca-certificates COPY cmd/registry/config-dev.yml /etc/docker/registry/config.yml -COPY --from=build /go/src/github.com/docker/distribution/bin/registry /bin/registry +COPY --from=build /usr/local/bin/registry /bin/registry VOLUME ["/var/lib/registry"] EXPOSE 5000 ENTRYPOINT ["registry"] diff -Nru docker-registry-2.7.1+ds2/docs/configuration.md docker-registry-2.8.0+ds1/docs/configuration.md --- docker-registry-2.7.1+ds2/docs/configuration.md 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/docs/configuration.md 2022-02-07 15:40:21.000000000 +0000 @@ -703,15 +703,20 @@ | `baseurl` | yes | The `SCHEME://HOST[/PATH]` at which Cloudfront is served. | | `privatekey` | yes | The private key for Cloudfront, provided by AWS. | | `keypairid` | yes | The key pair ID provided by AWS. | -| `duration` | no | An integer and unit for the duration of the Cloudfront session. Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, or `h`. For example, `3000s` is valid, but `3000 s` is not. If you do not specify a `duration` or you specify an integer without a time unit, the duration defaults to `20m` (20 minutes).| -|`ipfilteredby`|no | A string with the following value `none|aws|awsregion`. | -|`awsregion`|no | A comma separated string of AWS regions, only available when `ipfilteredby` is `awsregion`. For example, `us-east-1, us-west-2`| -|`updatefrenquency`|no | The frequency to update AWS IP regions, default: `12h`| -|`iprangesurl`|no | The URL contains the AWS IP ranges information, default: `https://ip-ranges.amazonaws.com/ip-ranges.json`| -Then value of ipfilteredby: -`none`: default, do not filter by IP -`aws`: IP from AWS goes to S3 directly -`awsregion`: IP from certain AWS regions goes to S3 directly, use together with `awsregion` +| `duration` | no | An integer and unit for the duration of the Cloudfront session. Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, or `h`. For example, `3000s` is valid, but `3000 s` is not. If you do not specify a `duration` or you specify an integer without a time unit, the duration defaults to `20m` (20 minutes). | +| `ipfilteredby` | no | A string with the following value `none`, `aws` or `awsregion`. | +| `awsregion` | no | A comma separated string of AWS regions, only available when `ipfilteredby` is `awsregion`. For example, `us-east-1, us-west-2` | +| `updatefrenquency` | no | The frequency to update AWS IP regions, default: `12h` | +| `iprangesurl` | no | The URL contains the AWS IP ranges information, default: `https://ip-ranges.amazonaws.com/ip-ranges.json` | + + +Value of `ipfilteredby` can be: + +| Value | Description | +|-------------|------------------------------------| +| `none` | default, do not filter by IP | +| `aws` | IP from AWS goes to S3 directly | +| `awsregion` | IP from certain AWS regions goes to S3 directly, use together with `awsregion`. | ### `redirect` @@ -777,6 +782,10 @@ clientcas: - /path/to/ca.pem - /path/to/another/ca.pem + minimumtls: tls1.2 + ciphersuites: + - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 letsencrypt: cachefile: /path/to/cache-file email: emailused@letsencrypt.com @@ -812,9 +821,49 @@ | Parameter | Required | Description | |-----------|----------|-------------------------------------------------------| -| `certificate` | yes | Absolute path to the x509 certificate file. | -| `key` | yes | Absolute path to the x509 private key file. | -| `clientcas` | no | An array of absolute paths to x509 CA files. | +| `certificate` | yes | Absolute path to the x509 certificate file. | +| `key` | yes | Absolute path to the x509 private key file. | +| `clientcas` | no | An array of absolute paths to x509 CA files. | +| `minimumtls` | no | Minimum TLS version allowed (tls1.0, tls1.1, tls1.2, tls1.3). Defaults to tls1.2 | +| `ciphersuites` | no | Cipher suites allowed. Please see below for allowed values and default. | + +Available cipher suites: +- TLS_RSA_WITH_RC4_128_SHA +- TLS_RSA_WITH_3DES_EDE_CBC_SHA +- TLS_RSA_WITH_AES_128_CBC_SHA +- TLS_RSA_WITH_AES_256_CBC_SHA +- TLS_RSA_WITH_AES_128_CBC_SHA256 +- TLS_RSA_WITH_AES_128_GCM_SHA256 +- TLS_RSA_WITH_AES_256_GCM_SHA384 +- TLS_ECDHE_ECDSA_WITH_RC4_128_SHA +- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA +- TLS_ECDHE_RSA_WITH_RC4_128_SHA +- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA +- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA +- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 +- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 +- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 +- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 +- TLS_AES_128_GCM_SHA256 +- TLS_AES_256_GCM_SHA384 +- TLS_CHACHA20_POLY1305_SHA256 + +Default cipher suites: +- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 +- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 +- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +- TLS_AES_128_GCM_SHA256 +- TLS_CHACHA20_POLY1305_SHA256 +- TLS_AES_256_GCM_SHA384 ### `letsencrypt` diff -Nru docker-registry-2.7.1+ds2/docs/spec/api.md docker-registry-2.8.0+ds1/docs/spec/api.md --- docker-registry-2.7.1+ds2/docs/spec/api.md 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/docs/spec/api.md 2022-02-07 15:40:21.000000000 +0000 @@ -2,6 +2,8 @@ title: "HTTP API V2" description: "Specification for the Registry API." keywords: registry, on-prem, images, tags, repository, distribution, api, advanced +redirect_from: + - /reference/api/registry_api/ --- # Docker Registry HTTP API V2 diff -Nru docker-registry-2.7.1+ds2/docs/spec/api.md.tmpl docker-registry-2.8.0+ds1/docs/spec/api.md.tmpl --- docker-registry-2.7.1+ds2/docs/spec/api.md.tmpl 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/docs/spec/api.md.tmpl 2022-02-07 15:40:21.000000000 +0000 @@ -2,6 +2,8 @@ title: "HTTP API V2" description: "Specification for the Registry API." keywords: registry, on-prem, images, tags, repository, distribution, api, advanced +redirect_from: + - /reference/api/registry_api/ --- # Docker Registry HTTP API V2 diff -Nru docker-registry-2.7.1+ds2/docs/spec/deprecated-schema-v1.md docker-registry-2.8.0+ds1/docs/spec/deprecated-schema-v1.md --- docker-registry-2.7.1+ds2/docs/spec/deprecated-schema-v1.md 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/docs/spec/deprecated-schema-v1.md 2022-02-07 15:40:21.000000000 +0000 @@ -0,0 +1,41 @@ +--- +title: Update deprecated schema image manifest version 2, v1 images +description: Update deprecated schema v1 iamges +keywords: registry, on-prem, images, tags, repository, distribution, api, advanced, manifest +--- + +## Image manifest version 2, schema 1 +With the release of image manifest version 2, schema 2, image manifest version +2, schema 1 has been deprecated. This could lead to compatibility and +vulnerability issues in images that haven't been updated to image manifest +version 2, schema 2. + +This page contains information on how to update from image manifest version 2, +schema 1. However, these instructions will not ensure your new image will run +successfully. There may be several other issues to troubleshoot that are +associated with the deprecated image manifest that will block your image from +running succesfully. A list of possible methods to help update your image is +also included below. + +### Update to image manifest version 2, schema 2 + +One way to upgrade an image from image manifest version 2, schema 1 to +schema 2 is to `docker pull` the image and then `docker push` the image with a +current version of Docker. Doing so will automatically convert the image to use +the latest image manifest specification. + +Converting an image to image manifest version 2, schema 2 converts the +manifest format, but does not update the contents within the image. Images +using manifest version 2, schema 1 may contain unpatched vulnerabilities. We +recommend looking for an alternative image or rebuilding it. + + +### Update FROM statement + +You can rebuild the image by updating the `FROM` statement in your +`Dockerfile`. If your image manifest is out-of-date, there is a chance the +image pulled from your `FROM` statement in your `Dockerfile` is also +out-of-date. See the [Dockerfile reference](https://docs.docker.com/engine/reference/builder/#from) +and the [Dockerfile best practices guide](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) +for more information on how to update the `FROM` statement in your +`Dockerfile`. diff -Nru docker-registry-2.7.1+ds2/docs/spec/manifest-v2-2.md docker-registry-2.8.0+ds1/docs/spec/manifest-v2-2.md --- docker-registry-2.7.1+ds2/docs/spec/manifest-v2-2.md 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/docs/spec/manifest-v2-2.md 2022-02-07 15:40:21.000000000 +0000 @@ -220,7 +220,7 @@ - **`urls`** *array* Provides a list of URLs from which the content may be fetched. Content - should be verified against the `digest` and `size`. This field is + must be verified against the `digest` and `size`. This field is optional and uncommon. ## Example Image Manifest diff -Nru docker-registry-2.7.1+ds2/.github/workflows/build.yml docker-registry-2.8.0+ds1/.github/workflows/build.yml --- docker-registry-2.7.1+ds2/.github/workflows/build.yml 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/.github/workflows/build.yml 2022-02-07 15:40:21.000000000 +0000 @@ -0,0 +1,93 @@ +name: build + +on: + push: + branches: + - 'release/*' + tags: + - 'v*' + pull_request: + +env: + DOCKERHUB_SLUG: distribution/distribution + +jobs: + build: + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - + name: Docker meta + id: meta + uses: docker/metadata-action@v3 + with: + images: | + ${{ env.DOCKERHUB_SLUG }} + ### versioning strategy + ### push semver tag v2.9.0 on main (default branch) + # distribution/distribution:2.9.0 + # distribution/distribution:latest + ### push semver tag v2.8.0 on release/2.8 branch + # distribution/distribution:2.8.0 + ### push on main + # distribution/distribution:edge + tags: | + type=semver,pattern={{version}} + type=ref,event=pr + # don't create latest tag on release/2.x + flavor: | + latest=false + labels: | + org.opencontainers.image.title=Distribution + org.opencontainers.image.description=The toolkit to pack, ship, store, and deliver container content + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - + name: Build artifacts + uses: docker/bake-action@v1 + with: + targets: artifact-all + - + name: Move artifacts + run: | + mv ./bin/**/* ./bin/ + - + name: Upload artifacts + uses: actions/upload-artifact@v2 + with: + name: registry + path: ./bin/* + if-no-files-found: error + - + name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build image + uses: docker/bake-action@v1 + with: + files: | + ./docker-bake.hcl + ${{ steps.meta.outputs.bake-file }} + targets: image-all + push: ${{ startsWith(github.ref, 'refs/tags/') }} + - + name: GitHub Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + draft: true + files: | + bin/*.tar.gz + bin/*.zip + bin/*.sha256 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff -Nru docker-registry-2.7.1+ds2/.github/workflows/ci.yml docker-registry-2.8.0+ds1/.github/workflows/ci.yml --- docker-registry-2.7.1+ds2/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/.github/workflows/ci.yml 2022-02-07 15:40:21.000000000 +0000 @@ -0,0 +1,50 @@ +name: CI + +on: + push: + pull_request: + +jobs: + + build: + runs-on: ubuntu-latest + env: + DOCKER_BUILDTAGS: "include_oss include_gcs" + CGO_ENABLED: 1 + GO111MODULE: "auto" + GOPATH: ${{ github.workspace }} + GOOS: linux + COMMIT_RANGE: ${{ github.event_name == 'pull_request' && format('{0}..{1}',github.event.pull_request.base.sha, github.event.pull_request.head.sha) || github.sha }} + + steps: + - uses: actions/checkout@v2 + with: + path: src/github.com/docker/distribution + fetch-depth: 50 + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.16.* + + - name: Dependencies + run: | + sudo apt-get -q update + sudo -E apt-get -yq --no-install-suggests --no-install-recommends install python2-minimal + cd /tmp && go get -u github.com/vbatts/git-validation + + - name: Build + working-directory: ./src/github.com/docker/distribution + run: | + DCO_VERBOSITY=-q script/validate/dco + GO111MODULE=on script/setup/install-dev-tools + script/validate/vendor + go build -i . + make check + make build + make binaries + if [ "$GOOS" = "linux" ]; then make coverage ; fi + + - uses: codecov/codecov-action@v1 + with: + directory: ./src/github.com/docker/distribution \ No newline at end of file diff -Nru docker-registry-2.7.1+ds2/.golangci.yml docker-registry-2.8.0+ds1/.golangci.yml --- docker-registry-2.7.1+ds2/.golangci.yml 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/.golangci.yml 2022-02-07 15:40:21.000000000 +0000 @@ -0,0 +1,20 @@ +linters: + enable: + - structcheck + - varcheck + - staticcheck + - unconvert + - gofmt + - goimports + - golint + - ineffassign + - vet + - unused + - misspell + disable: + - errcheck + +run: + deadline: 2m + skip-dirs: + - vendor diff -Nru docker-registry-2.7.1+ds2/.gometalinter.json docker-registry-2.8.0+ds1/.gometalinter.json --- docker-registry-2.7.1+ds2/.gometalinter.json 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/.gometalinter.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -{ - "Vendor": true, - "Deadline": "2m", - "Sort": ["linter", "severity", "path", "line"], - "EnableGC": true, - "Enable": [ - "structcheck", - "staticcheck", - "unconvert", - - "gofmt", - "goimports", - "golint", - "vet" - ] -} diff -Nru docker-registry-2.7.1+ds2/health/api/api.go docker-registry-2.8.0+ds1/health/api/api.go --- docker-registry-2.7.1+ds2/health/api/api.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/health/api/api.go 2022-02-07 15:40:21.000000000 +0000 @@ -14,7 +14,7 @@ // DownHandler registers a manual_http_status that always returns an Error func DownHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { - updater.Update(errors.New("Manual Check")) + updater.Update(errors.New("manual Check")) } else { w.WriteHeader(http.StatusNotFound) } diff -Nru docker-registry-2.7.1+ds2/.mailmap docker-registry-2.8.0+ds1/.mailmap --- docker-registry-2.7.1+ds2/.mailmap 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/.mailmap 2022-02-07 15:40:21.000000000 +0000 @@ -30,3 +30,17 @@ Mike Brown Mike Brown Manish Tomar Manish Tomar Sakeven Jiang sakeven +Milos Gajdos Milos Gajdos +Derek McGowan Derek McGowa +Adrian Plata Adrian Plata <@users.noreply.github.com> +Sebastiaan van Stijn Sebastiaan van Stijn +Vishesh Jindal Vishesh Jindal +Wang Yan Wang Yan +Chris Patterson Chris Patterson +Eohyung Lee Eohyung Lee +João Pereira <484633+joaodrp@users.noreply.github.com> +Smasherr Smasherr +Thomas Berger Thomas Berger +Samuel Karp Samuel Karp +Justin Cormack +sayboras diff -Nru docker-registry-2.7.1+ds2/Makefile docker-registry-2.8.0+ds1/Makefile --- docker-registry-2.7.1+ds2/Makefile 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/Makefile 2022-02-07 15:40:21.000000000 +0000 @@ -50,7 +50,7 @@ check: ## run all linters (TODO: enable "unused", "varcheck", "ineffassign", "unconvert", "staticheck", "goimports", "structcheck") @echo "$(WHALE) $@" - gometalinter --config .gometalinter.json ./... + golangci-lint run test: ## run tests, except integration test with test.short @echo "$(WHALE) $@" diff -Nru docker-registry-2.7.1+ds2/manifest/manifestlist/manifestlist.go docker-registry-2.8.0+ds1/manifest/manifestlist/manifestlist.go --- docker-registry-2.7.1+ds2/manifest/manifestlist/manifestlist.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/manifest/manifestlist/manifestlist.go 2022-02-07 15:40:21.000000000 +0000 @@ -8,7 +8,7 @@ "github.com/docker/distribution" "github.com/docker/distribution/manifest" "github.com/opencontainers/go-digest" - "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) const ( @@ -54,6 +54,9 @@ } imageIndexFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) { + if err := validateIndex(b); err != nil { + return nil, distribution.Descriptor{}, err + } m := new(DeserializedManifestList) err := m.UnmarshalJSON(b) if err != nil { @@ -163,7 +166,7 @@ }, } - m.Manifests = make([]ManifestDescriptor, len(descriptors), len(descriptors)) + m.Manifests = make([]ManifestDescriptor, len(descriptors)) copy(m.Manifests, descriptors) deserialized := DeserializedManifestList{ @@ -177,7 +180,7 @@ // UnmarshalJSON populates a new ManifestList struct from JSON data. func (m *DeserializedManifestList) UnmarshalJSON(b []byte) error { - m.canonical = make([]byte, len(b), len(b)) + m.canonical = make([]byte, len(b)) // store manifest list in canonical copy(m.canonical, b) @@ -214,3 +217,23 @@ return mediaType, m.canonical, nil } + +// unknownDocument represents a manifest, manifest list, or index that has not +// yet been validated +type unknownDocument struct { + Config interface{} `json:"config,omitempty"` + Layers interface{} `json:"layers,omitempty"` +} + +// validateIndex returns an error if the byte slice is invalid JSON or if it +// contains fields that belong to a manifest +func validateIndex(b []byte) error { + var doc unknownDocument + if err := json.Unmarshal(b, &doc); err != nil { + return err + } + if doc.Config != nil || doc.Layers != nil { + return errors.New("index: expected index but found manifest") + } + return nil +} diff -Nru docker-registry-2.7.1+ds2/manifest/manifestlist/manifestlist_test.go docker-registry-2.8.0+ds1/manifest/manifestlist/manifestlist_test.go --- docker-registry-2.7.1+ds2/manifest/manifestlist/manifestlist_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/manifest/manifestlist/manifestlist_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -7,7 +7,9 @@ "testing" "github.com/docker/distribution" - "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/docker/distribution/manifest/ocischema" + + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) var expectedManifestListSerialization = []byte(`{ @@ -303,3 +305,33 @@ mediaTypeTest(t, v1.MediaTypeImageIndex, v1.MediaTypeImageIndex, false) mediaTypeTest(t, v1.MediaTypeImageIndex, v1.MediaTypeImageIndex+"XXX", true) } + +func TestValidateManifest(t *testing.T) { + manifest := ocischema.Manifest{ + Config: distribution.Descriptor{Size: 1}, + Layers: []distribution.Descriptor{{Size: 2}}, + } + index := ManifestList{ + Manifests: []ManifestDescriptor{ + {Descriptor: distribution.Descriptor{Size: 3}}, + }, + } + t.Run("valid", func(t *testing.T) { + b, err := json.Marshal(index) + if err != nil { + t.Fatal("unexpected error marshaling index", err) + } + if err := validateIndex(b); err != nil { + t.Error("index should be valid", err) + } + }) + t.Run("invalid", func(t *testing.T) { + b, err := json.Marshal(manifest) + if err != nil { + t.Fatal("unexpected error marshaling manifest", err) + } + if err := validateIndex(b); err == nil { + t.Error("manifest should not be valid") + } + }) +} diff -Nru docker-registry-2.7.1+ds2/manifest/ocischema/builder.go docker-registry-2.8.0+ds1/manifest/ocischema/builder.go --- docker-registry-2.7.1+ds2/manifest/ocischema/builder.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/manifest/ocischema/builder.go 2022-02-07 15:40:21.000000000 +0000 @@ -7,7 +7,7 @@ "github.com/docker/distribution" "github.com/docker/distribution/manifest" "github.com/opencontainers/go-digest" - "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) // Builder is a type for constructing manifests. @@ -48,7 +48,7 @@ // valid media type for oci image manifests currently: "" or "application/vnd.oci.image.manifest.v1+json" func (mb *Builder) SetMediaType(mediaType string) error { if mediaType != "" && mediaType != v1.MediaTypeImageManifest { - return errors.New("Invalid media type for OCI image manifest") + return errors.New("invalid media type for OCI image manifest") } mb.mediaType = mediaType diff -Nru docker-registry-2.7.1+ds2/manifest/ocischema/builder_test.go docker-registry-2.8.0+ds1/manifest/ocischema/builder_test.go --- docker-registry-2.7.1+ds2/manifest/ocischema/builder_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/manifest/ocischema/builder_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -7,7 +7,7 @@ "github.com/docker/distribution" "github.com/opencontainers/go-digest" - "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) type mockBlobService struct { diff -Nru docker-registry-2.7.1+ds2/manifest/ocischema/manifest.go docker-registry-2.8.0+ds1/manifest/ocischema/manifest.go --- docker-registry-2.7.1+ds2/manifest/ocischema/manifest.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/manifest/ocischema/manifest.go 2022-02-07 15:40:21.000000000 +0000 @@ -8,7 +8,7 @@ "github.com/docker/distribution" "github.com/docker/distribution/manifest" "github.com/opencontainers/go-digest" - "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) var ( @@ -22,6 +22,9 @@ func init() { ocischemaFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) { + if err := validateManifest(b); err != nil { + return nil, distribution.Descriptor{}, err + } m := new(DeserializedManifest) err := m.UnmarshalJSON(b) if err != nil { @@ -87,7 +90,7 @@ // UnmarshalJSON populates a new Manifest struct from JSON data. func (m *DeserializedManifest) UnmarshalJSON(b []byte) error { - m.canonical = make([]byte, len(b), len(b)) + m.canonical = make([]byte, len(b)) // store manifest in canonical copy(m.canonical, b) @@ -122,3 +125,22 @@ func (m DeserializedManifest) Payload() (string, []byte, error) { return v1.MediaTypeImageManifest, m.canonical, nil } + +// unknownDocument represents a manifest, manifest list, or index that has not +// yet been validated +type unknownDocument struct { + Manifests interface{} `json:"manifests,omitempty"` +} + +// validateManifest returns an error if the byte slice is invalid JSON or if it +// contains fields that belong to a index +func validateManifest(b []byte) error { + var doc unknownDocument + if err := json.Unmarshal(b, &doc); err != nil { + return err + } + if doc.Manifests != nil { + return errors.New("ocimanifest: expected manifest but found index") + } + return nil +} diff -Nru docker-registry-2.7.1+ds2/manifest/ocischema/manifest_test.go docker-registry-2.8.0+ds1/manifest/ocischema/manifest_test.go --- docker-registry-2.7.1+ds2/manifest/ocischema/manifest_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/manifest/ocischema/manifest_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -8,7 +8,9 @@ "github.com/docker/distribution" "github.com/docker/distribution/manifest" - "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/docker/distribution/manifest/manifestlist" + + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) var expectedManifestSerialization = []byte(`{ @@ -182,3 +184,33 @@ mediaTypeTest(t, v1.MediaTypeImageManifest, false) mediaTypeTest(t, v1.MediaTypeImageManifest+"XXX", true) } + +func TestValidateManifest(t *testing.T) { + manifest := Manifest{ + Config: distribution.Descriptor{Size: 1}, + Layers: []distribution.Descriptor{{Size: 2}}, + } + index := manifestlist.ManifestList{ + Manifests: []manifestlist.ManifestDescriptor{ + {Descriptor: distribution.Descriptor{Size: 3}}, + }, + } + t.Run("valid", func(t *testing.T) { + b, err := json.Marshal(manifest) + if err != nil { + t.Fatal("unexpected error marshaling manifest", err) + } + if err := validateManifest(b); err != nil { + t.Error("manifest should be valid", err) + } + }) + t.Run("invalid", func(t *testing.T) { + b, err := json.Marshal(index) + if err != nil { + t.Fatal("unexpected error marshaling index", err) + } + if err := validateManifest(b); err == nil { + t.Error("index should not be valid") + } + }) +} diff -Nru docker-registry-2.7.1+ds2/manifest/schema1/manifest.go docker-registry-2.8.0+ds1/manifest/schema1/manifest.go --- docker-registry-2.7.1+ds2/manifest/schema1/manifest.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/manifest/schema1/manifest.go 2022-02-07 15:40:21.000000000 +0000 @@ -108,7 +108,7 @@ // UnmarshalJSON populates a new SignedManifest struct from JSON data. func (sm *SignedManifest) UnmarshalJSON(b []byte) error { - sm.all = make([]byte, len(b), len(b)) + sm.all = make([]byte, len(b)) // store manifest and signatures in all copy(sm.all, b) @@ -124,7 +124,7 @@ } // sm.Canonical stores the canonical manifest JSON - sm.Canonical = make([]byte, len(bytes), len(bytes)) + sm.Canonical = make([]byte, len(bytes)) copy(sm.Canonical, bytes) // Unmarshal canonical JSON into Manifest object diff -Nru docker-registry-2.7.1+ds2/manifest/schema1/reference_builder.go docker-registry-2.8.0+ds1/manifest/schema1/reference_builder.go --- docker-registry-2.7.1+ds2/manifest/schema1/reference_builder.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/manifest/schema1/reference_builder.go 2022-02-07 15:40:21.000000000 +0000 @@ -58,7 +58,7 @@ func (mb *referenceManifestBuilder) AppendReference(d distribution.Describable) error { r, ok := d.(Reference) if !ok { - return fmt.Errorf("Unable to add non-reference type to v1 builder") + return fmt.Errorf("unable to add non-reference type to v1 builder") } // Entries need to be prepended diff -Nru docker-registry-2.7.1+ds2/manifest/schema2/manifest.go docker-registry-2.8.0+ds1/manifest/schema2/manifest.go --- docker-registry-2.7.1+ds2/manifest/schema2/manifest.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/manifest/schema2/manifest.go 2022-02-07 15:40:21.000000000 +0000 @@ -106,7 +106,7 @@ // UnmarshalJSON populates a new Manifest struct from JSON data. func (m *DeserializedManifest) UnmarshalJSON(b []byte) error { - m.canonical = make([]byte, len(b), len(b)) + m.canonical = make([]byte, len(b)) // store manifest in canonical copy(m.canonical, b) diff -Nru docker-registry-2.7.1+ds2/manifests.go docker-registry-2.8.0+ds1/manifests.go --- docker-registry-2.7.1+ds2/manifests.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/manifests.go 2022-02-07 15:40:21.000000000 +0000 @@ -87,7 +87,7 @@ // UnmarshalFunc implements manifest unmarshalling a given MediaType type UnmarshalFunc func([]byte) (Manifest, Descriptor, error) -var mappings = make(map[string]UnmarshalFunc, 0) +var mappings = make(map[string]UnmarshalFunc) // UnmarshalManifest looks up manifest unmarshal functions based on // MediaType diff -Nru docker-registry-2.7.1+ds2/notifications/bridge.go docker-registry-2.8.0+ds1/notifications/bridge.go --- docker-registry-2.7.1+ds2/notifications/bridge.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/notifications/bridge.go 2022-02-07 15:40:21.000000000 +0000 @@ -125,15 +125,6 @@ return b.sink.Write(*event) } -func (b *bridge) createManifestEventAndWrite(action string, repo reference.Named, sm distribution.Manifest) error { - manifestEvent, err := b.createManifestEvent(action, repo, sm) - if err != nil { - return err - } - - return b.sink.Write(*manifestEvent) -} - func (b *bridge) createManifestDeleteEventAndWrite(action string, repo reference.Named, dgst digest.Digest) error { event := b.createEvent(action) event.Target.Repository = repo.Name() diff -Nru docker-registry-2.7.1+ds2/notifications/bridge_test.go docker-registry-2.8.0+ds1/notifications/bridge_test.go --- docker-registry-2.7.1+ds2/notifications/bridge_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/notifications/bridge_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -6,7 +6,7 @@ "github.com/docker/distribution" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/uuid" "github.com/docker/libtrust" "github.com/opencontainers/go-digest" diff -Nru docker-registry-2.7.1+ds2/notifications/event_test.go docker-registry-2.8.0+ds1/notifications/event_test.go --- docker-registry-2.7.1+ds2/notifications/event_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/notifications/event_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -114,8 +114,7 @@ prototype.Request.UserAgent = "test/0.1" prototype.Source.Addr = "hostname.local:port" - var manifestPush Event - manifestPush = prototype + var manifestPush = prototype manifestPush.ID = "asdf-asdf-asdf-asdf-0" manifestPush.Target.Digest = "sha256:0123456789abcdef0" manifestPush.Target.Length = 1 @@ -124,8 +123,7 @@ manifestPush.Target.Repository = "library/test" manifestPush.Target.URL = "http://example.com/v2/library/test/manifests/latest" - var layerPush0 Event - layerPush0 = prototype + var layerPush0 = prototype layerPush0.ID = "asdf-asdf-asdf-asdf-1" layerPush0.Target.Digest = "sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5" layerPush0.Target.Length = 2 @@ -134,8 +132,7 @@ layerPush0.Target.Repository = "library/test" layerPush0.Target.URL = "http://example.com/v2/library/test/manifests/latest" - var layerPush1 Event - layerPush1 = prototype + var layerPush1 = prototype layerPush1.ID = "asdf-asdf-asdf-asdf-2" layerPush1.Target.Digest = "sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d6" layerPush1.Target.Length = 3 diff -Nru docker-registry-2.7.1+ds2/notifications/http.go docker-registry-2.8.0+ds1/notifications/http.go --- docker-registry-2.7.1+ds2/notifications/http.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/notifications/http.go 2022-02-07 15:40:21.000000000 +0000 @@ -133,8 +133,7 @@ } func (hrt *headerRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - var nreq http.Request - nreq = *req + var nreq = *req nreq.Header = make(http.Header) merge := func(headers http.Header) { diff -Nru docker-registry-2.7.1+ds2/notifications/listener_test.go docker-registry-2.8.0+ds1/notifications/listener_test.go --- docker-registry-2.7.1+ds2/notifications/listener_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/notifications/listener_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -136,11 +136,10 @@ var blobDigests []digest.Digest blobs := repository.Blobs(ctx) for i := 0; i < 2; i++ { - rs, ds, err := testutil.CreateRandomTarFile() + rs, dgst, err := testutil.CreateRandomTarFile() if err != nil { t.Fatalf("error creating test layer: %v", err) } - dgst := digest.Digest(ds) blobDigests = append(blobDigests, dgst) wr, err := blobs.Create(ctx) diff -Nru docker-registry-2.7.1+ds2/notifications/sinks.go docker-registry-2.8.0+ds1/notifications/sinks.go --- docker-registry-2.7.1+ds2/notifications/sinks.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/notifications/sinks.go 2022-02-07 15:40:21.000000000 +0000 @@ -284,11 +284,6 @@ } } -type retryingSinkListener interface { - active(events ...Event) - retry(events ...Event) -} - // TODO(stevvooe): We are using circuit break here, which actually doesn't // make a whole lot of sense for this use case, since we always retry. Move // this to use bounded exponential backoff. diff -Nru docker-registry-2.7.1+ds2/README.md docker-registry-2.8.0+ds1/README.md --- docker-registry-2.7.1+ds2/README.md 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/README.md 2022-02-07 15:40:21.000000000 +0000 @@ -2,7 +2,7 @@ The Docker toolset to pack, ship, store, and deliver content. -This repository's main product is the Docker Registry 2.0 implementation +This repository provides the Docker Registry 2.0 implementation for storing and distributing Docker images. It supersedes the [docker/docker-registry](https://github.com/docker/docker-registry) project with a new API design, focused around security and performance. diff -Nru docker-registry-2.7.1+ds2/reference/normalize.go docker-registry-2.8.0+ds1/reference/normalize.go --- docker-registry-2.7.1+ds2/reference/normalize.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/reference/normalize.go 2022-02-07 15:40:21.000000000 +0000 @@ -56,6 +56,35 @@ return named, nil } +// ParseDockerRef normalizes the image reference following the docker convention. This is added +// mainly for backward compatibility. +// The reference returned can only be either tagged or digested. For reference contains both tag +// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@ +// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as +// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa. +func ParseDockerRef(ref string) (Named, error) { + named, err := ParseNormalizedNamed(ref) + if err != nil { + return nil, err + } + if _, ok := named.(NamedTagged); ok { + if canonical, ok := named.(Canonical); ok { + // The reference is both tagged and digested, only + // return digested. + newNamed, err := WithName(canonical.Name()) + if err != nil { + return nil, err + } + newCanonical, err := WithDigest(newNamed, canonical.Digest()) + if err != nil { + return nil, err + } + return newCanonical, nil + } + } + return TagNameOnly(named), nil +} + // splitDockerDomain splits a repository name to domain and remotename string. // If no valid domain is found, the default domain is used. Repository name // needs to be already validated before. diff -Nru docker-registry-2.7.1+ds2/reference/normalize_test.go docker-registry-2.8.0+ds1/reference/normalize_test.go --- docker-registry-2.7.1+ds2/reference/normalize_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/reference/normalize_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -623,3 +623,83 @@ } } } + +func TestParseDockerRef(t *testing.T) { + testcases := []struct { + name string + input string + expected string + }{ + { + name: "nothing", + input: "busybox", + expected: "docker.io/library/busybox:latest", + }, + { + name: "tag only", + input: "busybox:latest", + expected: "docker.io/library/busybox:latest", + }, + { + name: "digest only", + input: "busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582", + expected: "docker.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582", + }, + { + name: "path only", + input: "library/busybox", + expected: "docker.io/library/busybox:latest", + }, + { + name: "hostname only", + input: "docker.io/busybox", + expected: "docker.io/library/busybox:latest", + }, + { + name: "no tag", + input: "docker.io/library/busybox", + expected: "docker.io/library/busybox:latest", + }, + { + name: "no path", + input: "docker.io/busybox:latest", + expected: "docker.io/library/busybox:latest", + }, + { + name: "no hostname", + input: "library/busybox:latest", + expected: "docker.io/library/busybox:latest", + }, + { + name: "full reference with tag", + input: "docker.io/library/busybox:latest", + expected: "docker.io/library/busybox:latest", + }, + { + name: "gcr reference without tag", + input: "gcr.io/library/busybox", + expected: "gcr.io/library/busybox:latest", + }, + { + name: "both tag and digest", + input: "gcr.io/library/busybox:latest@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582", + expected: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582", + }, + } + for _, test := range testcases { + t.Run(test.name, func(t *testing.T) { + normalized, err := ParseDockerRef(test.input) + if err != nil { + t.Fatal(err) + } + output := normalized.String() + if output != test.expected { + t.Fatalf("expected %q to be parsed as %v, got %v", test.input, test.expected, output) + } + _, err = Parse(output) + if err != nil { + t.Fatalf("%q should be a valid reference, but got an error: %v", output, err) + } + }) + } +} diff -Nru docker-registry-2.7.1+ds2/reference/reference.go docker-registry-2.8.0+ds1/reference/reference.go --- docker-registry-2.7.1+ds2/reference/reference.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/reference/reference.go 2022-02-07 15:40:21.000000000 +0000 @@ -205,7 +205,7 @@ var repo repository nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1]) - if nameMatch != nil && len(nameMatch) == 3 { + if len(nameMatch) == 3 { repo.domain = nameMatch[1] repo.path = nameMatch[2] } else { diff -Nru docker-registry-2.7.1+ds2/reference/reference_test.go docker-registry-2.8.0+ds1/reference/reference_test.go --- docker-registry-2.7.1+ds2/reference/reference_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/reference/reference_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -639,7 +639,7 @@ failf("error parsing name: %s", err) continue } else if err == nil && testcase.err != nil { - failf("parsing succeded: expected error %v", testcase.err) + failf("parsing succeeded: expected error %v", testcase.err) continue } else if err != testcase.err { failf("unexpected error %v, expected %v", err, testcase.err) diff -Nru docker-registry-2.7.1+ds2/registry/api/errcode/errors.go docker-registry-2.8.0+ds1/registry/api/errcode/errors.go --- docker-registry-2.7.1+ds2/registry/api/errcode/errors.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/api/errcode/errors.go 2022-02-07 15:40:21.000000000 +0000 @@ -207,11 +207,11 @@ for _, daErr := range errs { var err Error - switch daErr.(type) { + switch daErr := daErr.(type) { case ErrorCode: - err = daErr.(ErrorCode).WithDetail(nil) + err = daErr.WithDetail(nil) case Error: - err = daErr.(Error) + err = daErr default: err = ErrorCodeUnknown.WithDetail(daErr) diff -Nru docker-registry-2.7.1+ds2/registry/api/v2/urls.go docker-registry-2.8.0+ds1/registry/api/v2/urls.go --- docker-registry-2.7.1+ds2/registry/api/v2/urls.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/api/v2/urls.go 2022-02-07 15:40:21.000000000 +0000 @@ -252,15 +252,3 @@ u.RawQuery = merged.Encode() return u } - -// appendValues appends the parameters to the url. Panics if the string is not -// a url. -func appendValues(u string, values ...url.Values) string { - up, err := url.Parse(u) - - if err != nil { - panic(err) // should never happen - } - - return appendValuesURL(up, values...).String() -} diff -Nru docker-registry-2.7.1+ds2/registry/api/v2/urls_test.go docker-registry-2.8.0+ds1/registry/api/v2/urls_test.go --- docker-registry-2.7.1+ds2/registry/api/v2/urls_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/api/v2/urls_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -182,11 +182,6 @@ doTest(false) } -type builderFromRequestTestCase struct { - request *http.Request - base string -} - func TestBuilderFromRequest(t *testing.T) { u, err := url.Parse("http://example.com") if err != nil { diff -Nru docker-registry-2.7.1+ds2/registry/client/auth/challenge/authchallenge.go docker-registry-2.8.0+ds1/registry/client/auth/challenge/authchallenge.go --- docker-registry-2.7.1+ds2/registry/client/auth/challenge/authchallenge.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/client/auth/challenge/authchallenge.go 2022-02-07 15:40:21.000000000 +0000 @@ -117,8 +117,8 @@ var t octetType isCtl := c <= 31 || c == 127 isChar := 0 <= c && c <= 127 - isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0 - if strings.IndexRune(" \t\r\n", rune(c)) >= 0 { + isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) + if strings.ContainsRune(" \t\r\n", rune(c)) { t |= isSpace } if isChar && !isCtl && !isSeparator { diff -Nru docker-registry-2.7.1+ds2/registry/client/auth/session_test.go docker-registry-2.8.0+ds1/registry/client/auth/session_test.go --- docker-registry-2.7.1+ds2/registry/client/auth/session_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/client/auth/session_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -466,7 +466,7 @@ }, }) - authenicate1 := fmt.Sprintf("Basic realm=localhost") + authenicate1 := "Basic realm=localhost" basicCheck := func(a string) bool { return a == fmt.Sprintf("Basic %s", basicAuth(username, password)) } @@ -546,7 +546,7 @@ }, }) - authenicate1 := fmt.Sprintf("Basic realm=localhost") + authenicate1 := "Basic realm=localhost" tokenExchanges := 0 basicCheck := func(a string) bool { tokenExchanges = tokenExchanges + 1 @@ -706,7 +706,7 @@ }, }) - authenicate1 := fmt.Sprintf("Basic realm=localhost") + authenicate1 := "Basic realm=localhost" tokenExchanges := 0 basicCheck := func(a string) bool { tokenExchanges = tokenExchanges + 1 @@ -835,7 +835,7 @@ username := "user1" password := "funSecretPa$$word" - authenicate := fmt.Sprintf("Basic realm=localhost") + authenicate := "Basic realm=localhost" validCheck := func(a string) bool { return a == fmt.Sprintf("Basic %s", basicAuth(username, password)) } diff -Nru docker-registry-2.7.1+ds2/registry/client/blob_writer_test.go docker-registry-2.8.0+ds1/registry/client/blob_writer_test.go --- docker-registry-2.7.1+ds2/registry/client/blob_writer_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/client/blob_writer_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -8,7 +8,7 @@ "github.com/docker/distribution" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/testutil" ) diff -Nru docker-registry-2.7.1+ds2/registry/client/repository.go docker-registry-2.8.0+ds1/registry/client/repository.go --- docker-registry-2.7.1+ds2/registry/client/repository.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/client/repository.go 2022-02-07 15:40:21.000000000 +0000 @@ -16,7 +16,7 @@ "github.com/docker/distribution" "github.com/docker/distribution/reference" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/client/transport" "github.com/docker/distribution/registry/storage/cache" "github.com/docker/distribution/registry/storage/cache/memory" @@ -736,7 +736,12 @@ return nil, err } - resp, err := bs.client.Post(u, "", nil) + req, err := http.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + resp, err := bs.client.Do(req) if err != nil { return nil, err } diff -Nru docker-registry-2.7.1+ds2/registry/client/repository_test.go docker-registry-2.8.0+ds1/registry/client/repository_test.go --- docker-registry-2.7.1+ds2/registry/client/repository_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/client/repository_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -22,7 +22,7 @@ "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/testutil" "github.com/docker/distribution/uuid" "github.com/docker/libtrust" @@ -152,7 +152,7 @@ if err != nil { t.Fatal(err) } - if bytes.Compare(b, b1) != 0 { + if !bytes.Equal(b, b1) { t.Fatalf("Wrong bytes values fetched: [%d]byte != [%d]byte", len(b), len(b1)) } diff -Nru docker-registry-2.7.1+ds2/registry/handlers/api_test.go docker-registry-2.8.0+ds1/registry/handlers/api_test.go --- docker-registry-2.7.1+ds2/registry/handlers/api_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/handlers/api_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -28,7 +28,7 @@ "github.com/docker/distribution/manifest/schema2" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" storagedriver "github.com/docker/distribution/registry/storage/driver" "github.com/docker/distribution/registry/storage/driver/factory" _ "github.com/docker/distribution/registry/storage/driver/testdriver" @@ -959,7 +959,6 @@ defer resp.Body.Close() checkResponse(t, "getting non-existent manifest", resp, expectedStatusCode) checkBodyHasErrorCodes(t, "getting non-existent manifest", resp, expectedErrorCode) - return } func testManifestAPISchema1(t *testing.T, env *testEnv, imageName reference.Named) manifestArgs { @@ -1066,12 +1065,11 @@ expectedLayers := make(map[digest.Digest]io.ReadSeeker) for i := range unsignedManifest.FSLayers { - rs, dgstStr, err := testutil.CreateRandomTarFile() + rs, dgst, err := testutil.CreateRandomTarFile() if err != nil { t.Fatalf("error creating random layer %d: %v", i, err) } - dgst := digest.Digest(dgstStr) expectedLayers[dgst] = rs unsignedManifest.FSLayers[i].BlobSum = dgst @@ -1405,12 +1403,11 @@ expectedLayers := make(map[digest.Digest]io.ReadSeeker) for i := range manifest.Layers { - rs, dgstStr, err := testutil.CreateRandomTarFile() + rs, dgst, err := testutil.CreateRandomTarFile() if err != nil { t.Fatalf("error creating random layer %d: %v", i, err) } - dgst := digest.Digest(dgstStr) expectedLayers[dgst] = rs manifest.Layers[i].Digest = dgst @@ -2357,7 +2354,7 @@ // Ensure that counts of expected errors were all non-zero for code := range expected { if counts[code] == 0 { - t.Fatalf("expected error code %v not encounterd during %s: %s", code, msg, string(p)) + t.Fatalf("expected error code %v not encountered during %s: %s", code, msg, string(p)) } } @@ -2432,11 +2429,10 @@ expectedLayers := make(map[digest.Digest]io.ReadSeeker) for i := range unsignedManifest.FSLayers { - rs, dgstStr, err := testutil.CreateRandomTarFile() + rs, dgst, err := testutil.CreateRandomTarFile() if err != nil { t.Fatalf("error creating random layer %d: %v", i, err) } - dgst := digest.Digest(dgstStr) expectedLayers[dgst] = rs unsignedManifest.FSLayers[i].BlobSum = dgst diff -Nru docker-registry-2.7.1+ds2/registry/handlers/app.go docker-registry-2.8.0+ds1/registry/handlers/app.go --- docker-registry-2.7.1+ds2/registry/handlers/app.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/handlers/app.go 2022-02-07 15:40:21.000000000 +0000 @@ -2,10 +2,11 @@ import ( "context" - cryptorand "crypto/rand" + "crypto/rand" "expvar" "fmt" - "math/rand" + "math" + "math/big" "net" "net/http" "net/url" @@ -24,7 +25,7 @@ "github.com/docker/distribution/notifications" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/auth" registrymiddleware "github.com/docker/distribution/registry/middleware/registry" repositorymiddleware "github.com/docker/distribution/registry/middleware/repository" @@ -610,7 +611,7 @@ func (app *App) configureSecret(configuration *configuration.Configuration) { if configuration.HTTP.Secret == "" { var secretBytes [randomSecretSize]byte - if _, err := cryptorand.Read(secretBytes[:]); err != nil { + if _, err := rand.Read(secretBytes[:]); err != nil { panic(fmt.Sprintf("could not generate random bytes for HTTP secret: %v", err)) } configuration.HTTP.Secret = string(secretBytes[:]) @@ -753,20 +754,18 @@ for _, e1 := range errors { var c context.Context - switch e1.(type) { + switch e := e1.(type) { case errcode.Error: - e, _ := e1.(errcode.Error) c = context.WithValue(ctx, errCodeKey{}, e.Code) c = context.WithValue(c, errMessageKey{}, e.Message) c = context.WithValue(c, errDetailKey{}, e.Detail) case errcode.ErrorCode: - e, _ := e1.(errcode.ErrorCode) c = context.WithValue(ctx, errCodeKey{}, e) c = context.WithValue(c, errMessageKey{}, e.Message()) default: // just normal go 'error' c = context.WithValue(ctx, errCodeKey{}, errcode.ErrorCodeUnknown) - c = context.WithValue(c, errMessageKey{}, e1.Error()) + c = context.WithValue(c, errMessageKey{}, e.Error()) } c = dcontext.WithLogger(c, dcontext.GetLogger(c, @@ -1062,8 +1061,13 @@ } go func() { - rand.Seed(time.Now().Unix()) - jitter := time.Duration(rand.Int()%60) * time.Minute + randInt, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64)) + if err != nil { + log.Infof("Failed to generate random jitter: %v", err) + // sleep 30min for failure case + randInt = big.NewInt(30) + } + jitter := time.Duration(randInt.Int64()%60) * time.Minute log.Infof("Starting upload purge in %s", jitter) time.Sleep(jitter) diff -Nru docker-registry-2.7.1+ds2/registry/handlers/app_test.go docker-registry-2.8.0+ds1/registry/handlers/app_test.go --- docker-registry-2.7.1+ds2/registry/handlers/app_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/handlers/app_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -11,7 +11,7 @@ "github.com/docker/distribution/configuration" "github.com/docker/distribution/context" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/auth" _ "github.com/docker/distribution/registry/auth/silly" "github.com/docker/distribution/registry/storage" diff -Nru docker-registry-2.7.1+ds2/registry/handlers/blob.go docker-registry-2.8.0+ds1/registry/handlers/blob.go --- docker-registry-2.7.1+ds2/registry/handlers/blob.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/handlers/blob.go 2022-02-07 15:40:21.000000000 +0000 @@ -6,7 +6,7 @@ "github.com/docker/distribution" "github.com/docker/distribution/context" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" "github.com/gorilla/handlers" "github.com/opencontainers/go-digest" ) diff -Nru docker-registry-2.7.1+ds2/registry/handlers/blobupload.go docker-registry-2.8.0+ds1/registry/handlers/blobupload.go --- docker-registry-2.7.1+ds2/registry/handlers/blobupload.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/handlers/blobupload.go 2022-02-07 15:40:21.000000000 +0000 @@ -9,7 +9,7 @@ dcontext "github.com/docker/distribution/context" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/storage" "github.com/gorilla/handlers" "github.com/opencontainers/go-digest" @@ -172,7 +172,7 @@ ct := r.Header.Get("Content-Type") if ct != "" && ct != "application/octet-stream" { - buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(fmt.Errorf("Bad Content-Type"))) + buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(fmt.Errorf("bad Content-Type"))) // TODO(dmcgowan): encode error return } diff -Nru docker-registry-2.7.1+ds2/registry/handlers/context.go docker-registry-2.8.0+ds1/registry/handlers/context.go --- docker-registry-2.7.1+ds2/registry/handlers/context.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/handlers/context.go 2022-02-07 15:40:21.000000000 +0000 @@ -8,7 +8,7 @@ "github.com/docker/distribution" dcontext "github.com/docker/distribution/context" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/auth" "github.com/opencontainers/go-digest" ) diff -Nru docker-registry-2.7.1+ds2/registry/handlers/hooks.go docker-registry-2.8.0+ds1/registry/handlers/hooks.go --- docker-registry-2.7.1+ds2/registry/handlers/hooks.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/handlers/hooks.go 2022-02-07 15:40:21.000000000 +0000 @@ -20,7 +20,7 @@ func (hook *logHook) Fire(entry *logrus.Entry) error { addr := strings.Split(hook.Mail.Addr, ":") if len(addr) != 2 { - return errors.New("Invalid Mail Address") + return errors.New("invalid Mail Address") } host := addr[0] subject := fmt.Sprintf("[%s] %s: %s", entry.Level, host, entry.Message) @@ -37,7 +37,7 @@ if err := t.Execute(b, entry); err != nil { return err } - body := fmt.Sprintf("%s", b) + body := b.String() return hook.Mail.sendMail(subject, body) } diff -Nru docker-registry-2.7.1+ds2/registry/handlers/mail.go docker-registry-2.8.0+ds1/registry/handlers/mail.go --- docker-registry-2.7.1+ds2/registry/handlers/mail.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/handlers/mail.go 2022-02-07 15:40:21.000000000 +0000 @@ -17,7 +17,7 @@ func (mail *mailer) sendMail(subject, message string) error { addr := strings.Split(mail.Addr, ":") if len(addr) != 2 { - return errors.New("Invalid Mail Address") + return errors.New("invalid Mail Address") } host := addr[0] msg := []byte("To:" + strings.Join(mail.To, ";") + diff -Nru docker-registry-2.7.1+ds2/registry/handlers/manifests.go docker-registry-2.8.0+ds1/registry/handlers/manifests.go --- docker-registry-2.7.1+ds2/registry/handlers/manifests.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/handlers/manifests.go 2022-02-07 15:40:21.000000000 +0000 @@ -14,11 +14,11 @@ "github.com/docker/distribution/manifest/schema2" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/auth" "github.com/gorilla/handlers" "github.com/opencontainers/go-digest" - "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) // These constants determine which architecture and OS to choose from a diff -Nru docker-registry-2.7.1+ds2/registry/handlers/tags.go docker-registry-2.8.0+ds1/registry/handlers/tags.go --- docker-registry-2.7.1+ds2/registry/handlers/tags.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/handlers/tags.go 2022-02-07 15:40:21.000000000 +0000 @@ -6,7 +6,7 @@ "github.com/docker/distribution" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" + v2 "github.com/docker/distribution/registry/api/v2" "github.com/gorilla/handlers" ) diff -Nru docker-registry-2.7.1+ds2/registry/proxy/proxyblobstore.go docker-registry-2.8.0+ds1/registry/proxy/proxyblobstore.go --- docker-registry-2.7.1+ds2/registry/proxy/proxyblobstore.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/proxy/proxyblobstore.go 2022-02-07 15:40:21.000000000 +0000 @@ -6,7 +6,6 @@ "net/http" "strconv" "sync" - "time" "github.com/docker/distribution" dcontext "github.com/docker/distribution/context" @@ -15,9 +14,6 @@ "github.com/opencontainers/go-digest" ) -// todo(richardscothern): from cache control header or config file -const blobTTL = 24 * 7 * time.Hour - type proxyBlobStore struct { localStore distribution.BlobStore remoteStore distribution.BlobService diff -Nru docker-registry-2.7.1+ds2/registry/proxy/proxyblobstore_test.go docker-registry-2.8.0+ds1/registry/proxy/proxyblobstore_test.go --- docker-registry-2.7.1+ds2/registry/proxy/proxyblobstore_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/proxy/proxyblobstore_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -193,7 +193,7 @@ } func makeBlob(size int) []byte { - blob := make([]byte, size, size) + blob := make([]byte, size) for i := 0; i < size; i++ { blob[i] = byte('A' + rand.Int()%48) } @@ -204,16 +204,6 @@ rand.Seed(42) } -func perm(m []distribution.Descriptor) []distribution.Descriptor { - for i := 0; i < len(m); i++ { - j := rand.Intn(i + 1) - tmp := m[i] - m[i] = m[j] - m[j] = tmp - } - return m -} - func populate(t *testing.T, te *testEnv, blobCount, size, numUnique int) { var inRemote []distribution.Descriptor diff -Nru docker-registry-2.7.1+ds2/registry/proxy/proxymanifeststore_test.go docker-registry-2.8.0+ds1/registry/proxy/proxymanifeststore_test.go --- docker-registry-2.7.1+ds2/registry/proxy/proxymanifeststore_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/proxy/proxymanifeststore_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -165,11 +165,10 @@ t.Fatalf("unexpected error creating test upload: %v", err) } - rs, ts, err := testutil.CreateRandomTarFile() + rs, dgst, err := testutil.CreateRandomTarFile() if err != nil { t.Fatalf("unexpected error generating test layer file") } - dgst := digest.Digest(ts) if _, err := io.Copy(wr, rs); err != nil { t.Fatalf("unexpected error copying to upload: %v", err) } diff -Nru docker-registry-2.7.1+ds2/registry/proxy/scheduler/scheduler.go docker-registry-2.8.0+ds1/registry/proxy/scheduler/scheduler.go --- docker-registry-2.7.1+ds2/registry/proxy/scheduler/scheduler.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/proxy/scheduler/scheduler.go 2022-02-07 15:40:21.000000000 +0000 @@ -118,7 +118,7 @@ } if !ttles.stopped { - return fmt.Errorf("Scheduler already started") + return fmt.Errorf("scheduler already started") } dcontext.GetLogger(ttles.ctx).Infof("Starting cached object TTL expiration scheduler...") @@ -126,7 +126,7 @@ // Start timer for each deserialized entry for _, entry := range ttles.entries { - entry.timer = ttles.startTimer(entry, entry.Expiry.Sub(time.Now())) + entry.timer = ttles.startTimer(entry, time.Until(entry.Expiry)) } // Start a ticker to periodically save the entries index @@ -164,7 +164,7 @@ Expiry: time.Now().Add(ttl), EntryType: eType, } - dcontext.GetLogger(ttles.ctx).Infof("Adding new scheduler entry for %s with ttl=%s", entry.Key, entry.Expiry.Sub(time.Now())) + dcontext.GetLogger(ttles.ctx).Infof("Adding new scheduler entry for %s with ttl=%s", entry.Key, time.Until(entry.Expiry)) if oldEntry, present := ttles.entries[entry.Key]; present && oldEntry.timer != nil { oldEntry.timer.Stop() } diff -Nru docker-registry-2.7.1+ds2/registry/registry.go docker-registry-2.8.0+ds1/registry/registry.go --- docker-registry-2.7.1+ds2/registry/registry.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/registry.go 2022-02-07 15:40:21.000000000 +0000 @@ -9,12 +9,14 @@ "net/http" "os" "os/signal" + "strings" "syscall" "time" "rsc.io/letsencrypt" - "github.com/Shopify/logrus-bugsnag" + logrus_bugsnag "github.com/Shopify/logrus-bugsnag" + logstash "github.com/bshuster-repo/logrus-logstash-hook" "github.com/bugsnag/bugsnag-go" "github.com/docker/distribution/configuration" @@ -31,6 +33,60 @@ "github.com/yvasiyarov/gorelic" ) +// a map of TLS cipher suite names to constants in https://golang.org/pkg/crypto/tls/#pkg-constants +var cipherSuites = map[string]uint16{ + // TLS 1.0 - 1.2 cipher suites + "TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA, + "TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, + "TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA, + "TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA, + "TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256, + "TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256, + "TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384, + "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + "TLS_ECDHE_RSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + // TLS 1.3 cipher suites + "TLS_AES_128_GCM_SHA256": tls.TLS_AES_128_GCM_SHA256, + "TLS_AES_256_GCM_SHA384": tls.TLS_AES_256_GCM_SHA384, + "TLS_CHACHA20_POLY1305_SHA256": tls.TLS_CHACHA20_POLY1305_SHA256, +} + +// a list of default ciphersuites to utilize +var defaultCipherSuites = []uint16{ + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_AES_128_GCM_SHA256, + tls.TLS_CHACHA20_POLY1305_SHA256, + tls.TLS_AES_256_GCM_SHA384, +} + +// maps tls version strings to constants +var defaultTLSVersionStr = "tls1.2" +var tlsVersions = map[string]uint16{ + // user specified values + "tls1.0": tls.VersionTLS10, + "tls1.1": tls.VersionTLS11, + "tls1.2": tls.VersionTLS12, + "tls1.3": tls.VersionTLS13, +} + // this channel gets notified when process receives signal. It is global to ease unit testing var quit = make(chan os.Signal, 1) @@ -125,6 +181,35 @@ }, nil } +// takes a list of cipher suites and converts it to a list of respective tls constants +// if an empty list is provided, then the defaults will be used +func getCipherSuites(names []string) ([]uint16, error) { + if len(names) == 0 { + return defaultCipherSuites, nil + } + cipherSuiteConsts := make([]uint16, len(names)) + for i, name := range names { + cipherSuiteConst, ok := cipherSuites[name] + if !ok { + return nil, fmt.Errorf("unknown TLS cipher suite '%s' specified for http.tls.cipherSuites", name) + } + cipherSuiteConsts[i] = cipherSuiteConst + } + return cipherSuiteConsts, nil +} + +// takes a list of cipher suite ids and converts it to a list of respective names +func getCipherSuiteNames(ids []uint16) []string { + if len(ids) == 0 { + return nil + } + names := make([]string, len(ids)) + for i, id := range ids { + names[i] = tls.CipherSuiteName(id) + } + return names +} + // ListenAndServe runs the registry's HTTP server. func (registry *Registry) ListenAndServe() error { config := registry.config @@ -135,19 +220,27 @@ } if config.HTTP.TLS.Certificate != "" || config.HTTP.TLS.LetsEncrypt.CacheFile != "" { + if config.HTTP.TLS.MinimumTLS == "" { + config.HTTP.TLS.MinimumTLS = defaultTLSVersionStr + } + tlsMinVersion, ok := tlsVersions[config.HTTP.TLS.MinimumTLS] + if !ok { + return fmt.Errorf("unknown minimum TLS level '%s' specified for http.tls.minimumtls", config.HTTP.TLS.MinimumTLS) + } + dcontext.GetLogger(registry.app).Infof("restricting TLS version to %s or higher", config.HTTP.TLS.MinimumTLS) + + tlsCipherSuites, err := getCipherSuites(config.HTTP.TLS.CipherSuites) + if err != nil { + return err + } + dcontext.GetLogger(registry.app).Infof("restricting TLS cipher suites to: %s", strings.Join(getCipherSuiteNames(tlsCipherSuites), ",")) + tlsConf := &tls.Config{ ClientAuth: tls.NoClientCert, NextProtos: nextProtos(config), - MinVersion: tls.VersionTLS10, + MinVersion: tlsMinVersion, PreferServerCipherSuites: true, - CipherSuites: []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - }, + CipherSuites: tlsCipherSuites, } if config.HTTP.TLS.LetsEncrypt.CacheFile != "" { @@ -185,7 +278,7 @@ } if ok := pool.AppendCertsFromPEM(caPem); !ok { - return fmt.Errorf("Could not add CA to pool") + return fmt.Errorf("could not add CA to pool") } } diff -Nru docker-registry-2.7.1+ds2/registry/registry_test.go docker-registry-2.8.0+ds1/registry/registry_test.go --- docker-registry-2.7.1+ds2/registry/registry_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/registry_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -3,12 +3,24 @@ import ( "bufio" "context" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" "fmt" "io/ioutil" + "math/big" "net" "net/http" "os" + "path" "reflect" + "strings" "testing" "time" @@ -38,18 +50,30 @@ } } -func setupRegistry() (*Registry, error) { +type registryTLSConfig struct { + cipherSuites []string + certificatePath string + privateKeyPath string + certificate *tls.Certificate +} + +func setupRegistry(tlsCfg *registryTLSConfig, addr string) (*Registry, error) { config := &configuration.Configuration{} // TODO: this needs to change to something ephemeral as the test will fail if there is any server // already listening on port 5000 - config.HTTP.Addr = ":5000" + config.HTTP.Addr = addr config.HTTP.DrainTimeout = time.Duration(10) * time.Second + if tlsCfg != nil { + config.HTTP.TLS.CipherSuites = tlsCfg.cipherSuites + config.HTTP.TLS.Certificate = tlsCfg.certificatePath + config.HTTP.TLS.Key = tlsCfg.privateKeyPath + } config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}} return NewRegistry(context.Background(), config) } func TestGracefulShutdown(t *testing.T) { - registry, err := setupRegistry() + registry, err := setupRegistry(nil, ":5000") if err != nil { t.Fatal(err) } @@ -98,3 +122,227 @@ t.Error("Body is not {}; ", string(body)) } } + +func TestGetCipherSuite(t *testing.T) { + resp, err := getCipherSuites([]string{"TLS_RSA_WITH_AES_128_CBC_SHA"}) + if err != nil || len(resp) != 1 || resp[0] != tls.TLS_RSA_WITH_AES_128_CBC_SHA { + t.Errorf("expected cipher suite %q, got %q", + "TLS_RSA_WITH_AES_128_CBC_SHA", + strings.Join(getCipherSuiteNames(resp), ","), + ) + } + + resp, err = getCipherSuites([]string{"TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_AES_128_GCM_SHA256"}) + if err != nil || len(resp) != 2 || + resp[0] != tls.TLS_RSA_WITH_AES_128_CBC_SHA || resp[1] != tls.TLS_AES_128_GCM_SHA256 { + t.Errorf("expected cipher suites %q, got %q", + "TLS_RSA_WITH_AES_128_CBC_SHA,TLS_AES_128_GCM_SHA256", + strings.Join(getCipherSuiteNames(resp), ","), + ) + } + + _, err = getCipherSuites([]string{"TLS_RSA_WITH_AES_128_CBC_SHA", "bad_input"}) + if err == nil { + t.Error("did not return expected error about unknown cipher suite") + } +} + +func buildRegistryTLSConfig(name, keyType string, cipherSuites []string) (*registryTLSConfig, error) { + var priv interface{} + var pub crypto.PublicKey + var err error + switch keyType { + case "rsa": + priv, err = rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return nil, fmt.Errorf("failed to create rsa private key: %v", err) + } + rsaKey := priv.(*rsa.PrivateKey) + pub = rsaKey.Public() + case "ecdsa": + priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + return nil, fmt.Errorf("failed to create ecdsa private key: %v", err) + } + ecdsaKey := priv.(*ecdsa.PrivateKey) + pub = ecdsaKey.Public() + default: + return nil, fmt.Errorf("unsupported key type: %v", keyType) + } + + notBefore := time.Now() + notAfter := notBefore.Add(time.Minute) + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + return nil, fmt.Errorf("failed to create serial number: %v", err) + } + cert := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{"registry_test"}, + }, + NotBefore: notBefore, + NotAfter: notAfter, + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, + DNSNames: []string{"localhost"}, + IsCA: true, + } + derBytes, err := x509.CreateCertificate(rand.Reader, &cert, &cert, pub, priv) + if err != nil { + return nil, fmt.Errorf("failed to create certificate: %v", err) + } + if _, err := os.Stat(os.TempDir()); os.IsNotExist(err) { + os.Mkdir(os.TempDir(), 1777) + } + + certPath := path.Join(os.TempDir(), name+".pem") + certOut, err := os.Create(certPath) + if err != nil { + return nil, fmt.Errorf("failed to create pem: %v", err) + } + if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { + return nil, fmt.Errorf("failed to write data to %s: %v", certPath, err) + } + if err := certOut.Close(); err != nil { + return nil, fmt.Errorf("error closing %s: %v", certPath, err) + } + + keyPath := path.Join(os.TempDir(), name+".key") + keyOut, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + return nil, fmt.Errorf("failed to open %s for writing: %v", keyPath, err) + } + privBytes, err := x509.MarshalPKCS8PrivateKey(priv) + if err != nil { + return nil, fmt.Errorf("unable to marshal private key: %v", err) + } + if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil { + return nil, fmt.Errorf("failed to write data to key.pem: %v", err) + } + if err := keyOut.Close(); err != nil { + return nil, fmt.Errorf("error closing %s: %v", keyPath, err) + } + + tlsCert := tls.Certificate{ + Certificate: [][]byte{derBytes}, + PrivateKey: priv, + } + + tlsTestCfg := registryTLSConfig{ + cipherSuites: cipherSuites, + certificatePath: certPath, + privateKeyPath: keyPath, + certificate: &tlsCert, + } + + return &tlsTestCfg, nil +} + +func TestRegistrySupportedCipherSuite(t *testing.T) { + name := "registry_test_server_supported_cipher" + cipherSuites := []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"} + serverTLS, err := buildRegistryTLSConfig(name, "rsa", cipherSuites) + if err != nil { + t.Fatal(err) + } + + registry, err := setupRegistry(serverTLS, ":5001") + if err != nil { + t.Fatal(err) + } + + // run registry server + var errchan chan error + go func() { + errchan <- registry.ListenAndServe() + }() + select { + case err = <-errchan: + t.Fatalf("Error listening: %v", err) + default: + } + + // Wait for some unknown random time for server to start listening + time.Sleep(3 * time.Second) + + // send tls request with server supported cipher suite + clientCipherSuites, err := getCipherSuites(cipherSuites) + if err != nil { + t.Fatal(err) + } + clientTLS := tls.Config{ + InsecureSkipVerify: true, + CipherSuites: clientCipherSuites, + } + dialer := net.Dialer{ + Timeout: time.Second * 5, + } + conn, err := tls.DialWithDialer(&dialer, "tcp", "127.0.0.1:5001", &clientTLS) + if err != nil { + t.Fatal(err) + } + fmt.Fprintf(conn, "GET /v2/ HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n") + + resp, err := http.ReadResponse(bufio.NewReader(conn), nil) + if err != nil { + t.Fatal(err) + } + if resp.Status != "200 OK" { + t.Error("response status is not 200 OK: ", resp.Status) + } + if body, err := ioutil.ReadAll(resp.Body); err != nil || string(body) != "{}" { + t.Error("Body is not {}; ", string(body)) + } + + // send stop signal + quit <- os.Interrupt + time.Sleep(100 * time.Millisecond) +} + +func TestRegistryUnsupportedCipherSuite(t *testing.T) { + name := "registry_test_server_unsupported_cipher" + serverTLS, err := buildRegistryTLSConfig(name, "rsa", []string{"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA358"}) + if err != nil { + t.Fatal(err) + } + + registry, err := setupRegistry(serverTLS, ":5002") + if err != nil { + t.Fatal(err) + } + + // run registry server + var errchan chan error + go func() { + errchan <- registry.ListenAndServe() + }() + select { + case err = <-errchan: + t.Fatalf("Error listening: %v", err) + default: + } + + // Wait for some unknown random time for server to start listening + time.Sleep(3 * time.Second) + + // send tls request with server unsupported cipher suite + clientTLS := tls.Config{ + InsecureSkipVerify: true, + CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + } + dialer := net.Dialer{ + Timeout: time.Second * 5, + } + _, err = tls.DialWithDialer(&dialer, "tcp", "127.0.0.1:5002", &clientTLS) + if err == nil { + t.Error("expected TLS connection to timeout") + } + + // send stop signal + quit <- os.Interrupt + time.Sleep(100 * time.Millisecond) +} diff -Nru docker-registry-2.7.1+ds2/registry/storage/blobstore.go docker-registry-2.8.0+ds1/registry/storage/blobstore.go --- docker-registry-2.7.1+ds2/registry/storage/blobstore.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/blobstore.go 2022-02-07 15:40:21.000000000 +0000 @@ -152,16 +152,6 @@ return linked, nil } -// resolve reads the digest link at path and returns the blob store path. -func (bs *blobStore) resolve(ctx context.Context, path string) (string, error) { - dgst, err := bs.readlink(ctx, path) - if err != nil { - return "", err - } - - return bs.path(dgst) -} - type blobStatter struct { driver driver.StorageDriver } diff -Nru docker-registry-2.7.1+ds2/registry/storage/blob_test.go docker-registry-2.8.0+ds1/registry/storage/blob_test.go --- docker-registry-2.7.1+ds2/registry/storage/blob_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/blob_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -418,7 +418,7 @@ bs := repository.Blobs(ctx) // Test destination for existence. - statDesc, err = bs.Stat(ctx, desc.Digest) + _, err = bs.Stat(ctx, desc.Digest) if err == nil { t.Fatalf("unexpected non-error stating unmounted blob: %v", desc) } @@ -478,12 +478,12 @@ t.Fatalf("Unexpected error deleting blob") } - d, err := bs.Stat(ctx, desc.Digest) + _, err = bs.Stat(ctx, desc.Digest) if err != nil { t.Fatalf("unexpected error stating blob deleted from source repository: %v", err) } - d, err = sbs.Stat(ctx, desc.Digest) + d, err := sbs.Stat(ctx, desc.Digest) if err == nil { t.Fatalf("unexpected non-error stating deleted blob: %v", d) } diff -Nru docker-registry-2.7.1+ds2/registry/storage/cache/cachecheck/suite.go docker-registry-2.8.0+ds1/registry/storage/cache/cachecheck/suite.go --- docker-registry-2.7.1+ds2/registry/storage/cache/cachecheck/suite.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/cache/cachecheck/suite.go 2022-02-07 15:40:21.000000000 +0000 @@ -173,8 +173,7 @@ t.Error(err) } - desc, err = cache.Stat(ctx, localDigest) - if err == nil { + if _, err = cache.Stat(ctx, localDigest); err == nil { t.Fatalf("expected error statting deleted blob: %v", err) } } diff -Nru docker-registry-2.7.1+ds2/registry/storage/driver/azure/azure.go docker-registry-2.8.0+ds1/registry/storage/driver/azure/azure.go --- docker-registry-2.7.1+ds2/registry/storage/driver/azure/azure.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/driver/azure/azure.go 2022-02-07 15:40:21.000000000 +0000 @@ -55,17 +55,17 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) { accountName, ok := parameters[paramAccountName] if !ok || fmt.Sprint(accountName) == "" { - return nil, fmt.Errorf("No %s parameter provided", paramAccountName) + return nil, fmt.Errorf("no %s parameter provided", paramAccountName) } accountKey, ok := parameters[paramAccountKey] if !ok || fmt.Sprint(accountKey) == "" { - return nil, fmt.Errorf("No %s parameter provided", paramAccountKey) + return nil, fmt.Errorf("no %s parameter provided", paramAccountKey) } container, ok := parameters[paramContainer] if !ok || fmt.Sprint(container) == "" { - return nil, fmt.Errorf("No %s parameter provided", paramContainer) + return nil, fmt.Errorf("no %s parameter provided", paramContainer) } realm, ok := parameters[paramRealm] diff -Nru docker-registry-2.7.1+ds2/registry/storage/driver/filesystem/driver_test.go docker-registry-2.8.0+ds1/registry/storage/driver/filesystem/driver_test.go --- docker-registry-2.7.1+ds2/registry/storage/driver/filesystem/driver_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/driver/filesystem/driver_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -36,7 +36,7 @@ func TestFromParametersImpl(t *testing.T) { tests := []struct { - params map[string]interface{} // techincally the yaml can contain anything + params map[string]interface{} // technically the yaml can contain anything expected DriverParameters pass bool }{ diff -Nru docker-registry-2.7.1+ds2/registry/storage/driver/inmemory/mfs.go docker-registry-2.8.0+ds1/registry/storage/driver/inmemory/mfs.go --- docker-registry-2.7.1+ds2/registry/storage/driver/inmemory/mfs.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/driver/inmemory/mfs.go 2022-02-07 15:40:21.000000000 +0000 @@ -252,20 +252,6 @@ return nil } -// dump outputs a primitive directory structure to stdout. -func (d *dir) dump(indent string) { - fmt.Println(indent, d.name()+"/") - - for _, child := range d.children { - if child.isdir() { - child.(*dir).dump(indent + "\t") - } else { - fmt.Println(indent, child.name()) - } - - } -} - func (d *dir) String() string { return fmt.Sprintf("&dir{path: %v, children: %v}", d.p, d.children) } diff -Nru docker-registry-2.7.1+ds2/registry/storage/driver/middleware/cloudfront/middleware.go docker-registry-2.8.0+ds1/registry/storage/driver/middleware/cloudfront/middleware.go --- docker-registry-2.7.1+ds2/registry/storage/driver/middleware/cloudfront/middleware.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/driver/middleware/cloudfront/middleware.go 2022-02-07 15:40:21.000000000 +0000 @@ -16,7 +16,7 @@ "github.com/aws/aws-sdk-go/service/cloudfront/sign" dcontext "github.com/docker/distribution/context" storagedriver "github.com/docker/distribution/registry/storage/driver" - "github.com/docker/distribution/registry/storage/driver/middleware" + storagemiddleware "github.com/docker/distribution/registry/storage/driver/middleware" ) // cloudFrontStorageMiddleware provides a simple implementation of layerHandler that @@ -138,27 +138,33 @@ // parse ipfilteredby var awsIPs *awsIPs - if ipFilteredBy := options["ipfilteredby"].(string); ok { - switch strings.ToLower(strings.TrimSpace(ipFilteredBy)) { - case "", "none": - awsIPs = nil - case "aws": - newAWSIPs(ipRangesURL, updateFrequency, nil) - case "awsregion": - var awsRegion []string - if regions, ok := options["awsregion"].(string); ok { - for _, awsRegions := range strings.Split(regions, ",") { - awsRegion = append(awsRegion, strings.ToLower(strings.TrimSpace(awsRegions))) + if i, ok := options["ipfilteredby"]; ok { + if ipFilteredBy, ok := i.(string); ok { + switch strings.ToLower(strings.TrimSpace(ipFilteredBy)) { + case "", "none": + awsIPs = nil + case "aws": + awsIPs = newAWSIPs(ipRangesURL, updateFrequency, nil) + case "awsregion": + var awsRegion []string + if i, ok := options["awsregion"]; ok { + if regions, ok := i.(string); ok { + for _, awsRegions := range strings.Split(regions, ",") { + awsRegion = append(awsRegion, strings.ToLower(strings.TrimSpace(awsRegions))) + } + awsIPs = newAWSIPs(ipRangesURL, updateFrequency, awsRegion) + } else { + return nil, fmt.Errorf("awsRegion must be a comma separated string of valid aws regions") + } + } else { + return nil, fmt.Errorf("awsRegion is not defined") } - awsIPs = newAWSIPs(ipRangesURL, updateFrequency, awsRegion) - } else { - return nil, fmt.Errorf("awsRegion must be a comma separated string of valid aws regions") + default: + return nil, fmt.Errorf("ipfilteredby only allows a string the following value: none|aws|awsregion") } - default: - return nil, fmt.Errorf("ipfilteredby only allows a string the following value: none|aws|awsregion") + } else { + return nil, fmt.Errorf("ipfilteredby only allows a string with the following value: none|aws|awsregion") } - } else { - return nil, fmt.Errorf("ipfilteredby only allows a string with the following value: none|aws|awsregion") } return &cloudFrontStorageMiddleware{ diff -Nru docker-registry-2.7.1+ds2/registry/storage/driver/s3-aws/s3.go docker-registry-2.8.0+ds1/registry/storage/driver/s3-aws/s3.go --- docker-registry-2.7.1+ds2/registry/storage/driver/s3-aws/s3.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/driver/s3-aws/s3.go 2022-02-07 15:40:21.000000000 +0000 @@ -188,19 +188,19 @@ regionName := parameters["region"] if regionName == nil || fmt.Sprint(regionName) == "" { - return nil, fmt.Errorf("No region parameter provided") + return nil, fmt.Errorf("no region parameter provided") } region := fmt.Sprint(regionName) // Don't check the region value if a custom endpoint is provided. if regionEndpoint == "" { if _, ok := validRegions[region]; !ok { - return nil, fmt.Errorf("Invalid region provided: %v", region) + return nil, fmt.Errorf("invalid region provided: %v", region) } } bucket := parameters["bucket"] if bucket == nil || fmt.Sprint(bucket) == "" { - return nil, fmt.Errorf("No bucket parameter provided") + return nil, fmt.Errorf("no bucket parameter provided") } encryptBool := false @@ -209,7 +209,7 @@ case string: b, err := strconv.ParseBool(encrypt) if err != nil { - return nil, fmt.Errorf("The encrypt parameter should be a boolean") + return nil, fmt.Errorf("the encrypt parameter should be a boolean") } encryptBool = b case bool: @@ -217,7 +217,7 @@ case nil: // do nothing default: - return nil, fmt.Errorf("The encrypt parameter should be a boolean") + return nil, fmt.Errorf("the encrypt parameter should be a boolean") } secureBool := true @@ -226,7 +226,7 @@ case string: b, err := strconv.ParseBool(secure) if err != nil { - return nil, fmt.Errorf("The secure parameter should be a boolean") + return nil, fmt.Errorf("the secure parameter should be a boolean") } secureBool = b case bool: @@ -234,7 +234,7 @@ case nil: // do nothing default: - return nil, fmt.Errorf("The secure parameter should be a boolean") + return nil, fmt.Errorf("the secure parameter should be a boolean") } skipVerifyBool := false @@ -243,7 +243,7 @@ case string: b, err := strconv.ParseBool(skipVerify) if err != nil { - return nil, fmt.Errorf("The skipVerify parameter should be a boolean") + return nil, fmt.Errorf("the skipVerify parameter should be a boolean") } skipVerifyBool = b case bool: @@ -251,7 +251,7 @@ case nil: // do nothing default: - return nil, fmt.Errorf("The skipVerify parameter should be a boolean") + return nil, fmt.Errorf("the skipVerify parameter should be a boolean") } v4Bool := true @@ -260,7 +260,7 @@ case string: b, err := strconv.ParseBool(v4auth) if err != nil { - return nil, fmt.Errorf("The v4auth parameter should be a boolean") + return nil, fmt.Errorf("the v4auth parameter should be a boolean") } v4Bool = b case bool: @@ -268,7 +268,7 @@ case nil: // do nothing default: - return nil, fmt.Errorf("The v4auth parameter should be a boolean") + return nil, fmt.Errorf("the v4auth parameter should be a boolean") } keyID := parameters["keyid"] @@ -306,7 +306,7 @@ if storageClassParam != nil { storageClassString, ok := storageClassParam.(string) if !ok { - return nil, fmt.Errorf("The storageclass parameter must be one of %v, %v invalid", + return nil, fmt.Errorf("the storageclass parameter must be one of %v, %v invalid", []string{s3.StorageClassStandard, s3.StorageClassReducedRedundancy}, storageClassParam) } // All valid storage class parameters are UPPERCASE, so be a bit more flexible here @@ -314,7 +314,7 @@ if storageClassString != noStorageClass && storageClassString != s3.StorageClassStandard && storageClassString != s3.StorageClassReducedRedundancy { - return nil, fmt.Errorf("The storageclass parameter must be one of %v, %v invalid", + return nil, fmt.Errorf("the storageclass parameter must be one of %v, %v invalid", []string{noStorageClass, s3.StorageClassStandard, s3.StorageClassReducedRedundancy}, storageClassParam) } storageClass = storageClassString @@ -330,11 +330,11 @@ if objectACLParam != nil { objectACLString, ok := objectACLParam.(string) if !ok { - return nil, fmt.Errorf("Invalid value for objectacl parameter: %v", objectACLParam) + return nil, fmt.Errorf("invalid value for objectacl parameter: %v", objectACLParam) } if _, ok = validObjectACLs[objectACLString]; !ok { - return nil, fmt.Errorf("Invalid value for objectacl parameter: %v", objectACLParam) + return nil, fmt.Errorf("invalid value for objectacl parameter: %v", objectACLParam) } objectACL = objectACLString } @@ -366,7 +366,7 @@ return New(params) } -// getParameterAsInt64 converts paramaters[name] to an int64 value (using +// getParameterAsInt64 converts parameters[name] to an int64 value (using // defaultt if nil), verifies it is no smaller than min, and returns it. func getParameterAsInt64(parameters map[string]interface{}, name string, defaultt int64, min int64, max int64) (int64, error) { rv := defaultt @@ -389,7 +389,7 @@ } if rv < min || rv > max { - return 0, fmt.Errorf("The %s %#v parameter should be a number between %d and %d (inclusive)", name, rv, min, max) + return 0, fmt.Errorf("the %s %#v parameter should be a number between %d and %d (inclusive)", name, rv, min, max) } return rv, nil @@ -401,7 +401,7 @@ if !params.V4Auth && (params.RegionEndpoint == "" || strings.Contains(params.RegionEndpoint, "s3.amazonaws.com")) { - return nil, fmt.Errorf("On Amazon S3 this storage driver can only be used with v4 authentication") + return nil, fmt.Errorf("on Amazon S3 this storage driver can only be used with v4 authentication") } awsConfig := aws.NewConfig() @@ -878,7 +878,7 @@ if ok { et, ok := expires.(time.Time) if ok { - expiresIn = et.Sub(time.Now()) + expiresIn = time.Until(et) } } @@ -970,8 +970,19 @@ defer done("s3aws.ListObjectsV2Pages(%s)", path) listObjectErr := d.S3.ListObjectsV2PagesWithContext(ctx, listObjectsInput, func(objects *s3.ListObjectsV2Output, lastPage bool) bool { - *objectCount += *objects.KeyCount - walkInfos := make([]walkInfoContainer, 0, *objects.KeyCount) + var count int64 + // KeyCount was introduced with version 2 of the GET Bucket operation in S3. + // Some S3 implementations don't support V2 now, so we fall back to manual + // calculation of the key count if required + if objects.KeyCount != nil { + count = *objects.KeyCount + *objectCount += *objects.KeyCount + } else { + count = int64(len(objects.Contents) + len(objects.CommonPrefixes)) + *objectCount += count + } + + walkInfos := make([]walkInfoContainer, 0, count) for _, dir := range objects.CommonPrefixes { commonPrefix := *dir.Prefix diff -Nru docker-registry-2.7.1+ds2/registry/storage/driver/s3-aws/s3_v2_signer.go docker-registry-2.8.0+ds1/registry/storage/driver/s3-aws/s3_v2_signer.go --- docker-registry-2.7.1+ds2/registry/storage/driver/s3-aws/s3_v2_signer.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/driver/s3-aws/s3_v2_signer.go 2022-02-07 15:40:21.000000000 +0000 @@ -39,12 +39,6 @@ log "github.com/sirupsen/logrus" ) -const ( - signatureVersion = "2" - signatureMethod = "HmacSHA1" - timeFormat = "2006-01-02T15:04:05Z" -) - type signer struct { // Values that must be populated from the request Request *http.Request diff -Nru docker-registry-2.7.1+ds2/registry/storage/driver/swift/swift.go docker-registry-2.8.0+ds1/registry/storage/driver/swift/swift.go --- docker-registry-2.7.1+ds2/registry/storage/driver/swift/swift.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/driver/swift/swift.go 2022-02-07 15:40:21.000000000 +0000 @@ -160,23 +160,23 @@ } if params.Username == "" { - return nil, fmt.Errorf("No username parameter provided") + return nil, fmt.Errorf("no username parameter provided") } if params.Password == "" { - return nil, fmt.Errorf("No password parameter provided") + return nil, fmt.Errorf("no password parameter provided") } if params.AuthURL == "" { - return nil, fmt.Errorf("No authurl parameter provided") + return nil, fmt.Errorf("no authurl parameter provided") } if params.Container == "" { - return nil, fmt.Errorf("No container parameter provided") + return nil, fmt.Errorf("no container parameter provided") } if params.ChunkSize < minChunkSize { - return nil, fmt.Errorf("The chunksize %#v parameter should be a number that is larger than or equal to %d", params.ChunkSize, minChunkSize) + return nil, fmt.Errorf("the chunksize %#v parameter should be a number that is larger than or equal to %d", params.ChunkSize, minChunkSize) } return New(params) @@ -211,15 +211,15 @@ } err := ct.Authenticate() if err != nil { - return nil, fmt.Errorf("Swift authentication failed: %s", err) + return nil, fmt.Errorf("swift authentication failed: %s", err) } if _, _, err := ct.Container(params.Container); err == swift.ContainerNotFound { if err := ct.ContainerCreate(params.Container, nil); err != nil { - return nil, fmt.Errorf("Failed to create container %s (%s)", params.Container, err) + return nil, fmt.Errorf("failed to create container %s (%s)", params.Container, err) } } else if err != nil { - return nil, fmt.Errorf("Failed to retrieve info about container %s (%s)", params.Container, err) + return nil, fmt.Errorf("failed to retrieve info about container %s (%s)", params.Container, err) } d := &driver{ @@ -258,7 +258,7 @@ if d.TempURLContainerKey { _, containerHeaders, err := d.Conn.Container(d.Container) if err != nil { - return nil, fmt.Errorf("Failed to fetch container info %s (%s)", d.Container, err) + return nil, fmt.Errorf("failed to fetch container info %s (%s)", d.Container, err) } d.SecretKey = containerHeaders["X-Container-Meta-Temp-Url-Key"] @@ -273,7 +273,7 @@ // Use the account secret key _, accountHeaders, err := d.Conn.Account() if err != nil { - return nil, fmt.Errorf("Failed to fetch account info (%s)", err) + return nil, fmt.Errorf("failed to fetch account info (%s)", err) } d.SecretKey = accountHeaders["X-Account-Meta-Temp-Url-Key"] @@ -350,7 +350,7 @@ } if isDLO && size == 0 { if time.Now().Add(waitingTime).After(endTime) { - return nil, fmt.Errorf("Timeout expired while waiting for segments of %s to show up", path) + return nil, fmt.Errorf("timeout expired while waiting for segments of %s to show up", path) } time.Sleep(waitingTime) waitingTime *= 2 @@ -456,7 +456,7 @@ _, isDLO := headers["X-Object-Manifest"] if isDLO && info.Bytes == 0 { if time.Now().Add(waitingTime).After(endTime) { - return nil, fmt.Errorf("Timeout expired while waiting for segments of %s to show up", path) + return nil, fmt.Errorf("timeout expired while waiting for segments of %s to show up", path) } time.Sleep(waitingTime) waitingTime *= 2 @@ -755,7 +755,7 @@ chunks = append(chunks, slice[offset:offset+chunkSize]) } } else { - return nil, fmt.Errorf("Max chunk size must be > 0") + return nil, fmt.Errorf("max chunk size must be > 0") } return } @@ -894,7 +894,7 @@ if info.Bytes == w.size { break } - err = fmt.Errorf("Timeout expired while waiting for segments of %s to show up", w.path) + err = fmt.Errorf("timeout expired while waiting for segments of %s to show up", w.path) } if time.Now().Add(waitingTime).After(endTime) { break diff -Nru docker-registry-2.7.1+ds2/registry/storage/garbagecollect.go docker-registry-2.8.0+ds1/registry/storage/garbagecollect.go --- docker-registry-2.7.1+ds2/registry/storage/garbagecollect.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/garbagecollect.go 2022-02-07 15:40:21.000000000 +0000 @@ -98,15 +98,13 @@ return nil }) - if err != nil { - // In certain situations such as unfinished uploads, deleting all - // tags in S3 or removing the _manifests folder manually, this - // error may be of type PathNotFound. - // - // In these cases we can continue marking other manifests safely. - if _, ok := err.(driver.PathNotFoundError); ok { - return nil - } + // In certain situations such as unfinished uploads, deleting all + // tags in S3 or removing the _manifests folder manually, this + // error may be of type PathNotFound. + // + // In these cases we can continue marking other manifests safely. + if _, ok := err.(driver.PathNotFoundError); ok { + return nil } return err diff -Nru docker-registry-2.7.1+ds2/registry/storage/io.go docker-registry-2.8.0+ds1/registry/storage/io.go --- docker-registry-2.7.1+ds2/registry/storage/io.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/io.go 2022-02-07 15:40:21.000000000 +0000 @@ -18,6 +18,7 @@ if err != nil { return nil, err } + defer r.Close() return readAllLimited(r, maxBlobGetSize) } diff -Nru docker-registry-2.7.1+ds2/registry/storage/linkedblobstore_test.go docker-registry-2.8.0+ds1/registry/storage/linkedblobstore_test.go --- docker-registry-2.7.1+ds2/registry/storage/linkedblobstore_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/linkedblobstore_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -27,13 +27,12 @@ // readseekers for upload later. testLayers := map[digest.Digest]io.ReadSeeker{} for i := 0; i < 2; i++ { - rs, ds, err := testutil.CreateRandomTarFile() + rs, dgst, err := testutil.CreateRandomTarFile() if err != nil { t.Fatalf("unexpected error generating test layer file") } - dgst := digest.Digest(ds) - testLayers[digest.Digest(dgst)] = rs + testLayers[dgst] = rs } // upload the layers to foo/bar diff -Nru docker-registry-2.7.1+ds2/registry/storage/manifeststore.go docker-registry-2.8.0+ds1/registry/storage/manifeststore.go --- docker-registry-2.7.1+ds2/registry/storage/manifeststore.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/manifeststore.go 2022-02-07 15:40:21.000000000 +0000 @@ -13,7 +13,7 @@ "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" "github.com/opencontainers/go-digest" - "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) // A ManifestHandler gets and puts manifests of a particular type. diff -Nru docker-registry-2.7.1+ds2/registry/storage/manifeststore_test.go docker-registry-2.8.0+ds1/registry/storage/manifeststore_test.go --- docker-registry-2.7.1+ds2/registry/storage/manifeststore_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/manifeststore_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -19,7 +19,7 @@ "github.com/docker/distribution/testutil" "github.com/docker/libtrust" "github.com/opencontainers/go-digest" - "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) type manifestStoreTestEnv struct { @@ -91,13 +91,12 @@ // readseekers for upload later. testLayers := map[digest.Digest]io.ReadSeeker{} for i := 0; i < 2; i++ { - rs, ds, err := testutil.CreateRandomTarFile() + rs, dgst, err := testutil.CreateRandomTarFile() if err != nil { t.Fatalf("unexpected error generating test layer file") } - dgst := digest.Digest(ds) - testLayers[digest.Digest(dgst)] = rs + testLayers[dgst] = rs m.FSLayers = append(m.FSLayers, schema1.FSLayer{ BlobSum: dgst, }) @@ -414,11 +413,10 @@ // Add some layers for i := 0; i < 2; i++ { - rs, ds, err := testutil.CreateRandomTarFile() + rs, dgst, err := testutil.CreateRandomTarFile() if err != nil { t.Fatalf("%s: unexpected error generating test layer file", testname) } - dgst := digest.Digest(ds) wr, err := env.repository.Blobs(env.ctx).Create(env.ctx) if err != nil { diff -Nru docker-registry-2.7.1+ds2/registry/storage/ocimanifesthandler.go docker-registry-2.8.0+ds1/registry/storage/ocimanifesthandler.go --- docker-registry-2.7.1+ds2/registry/storage/ocimanifesthandler.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/ocimanifesthandler.go 2022-02-07 15:40:21.000000000 +0000 @@ -9,7 +9,7 @@ dcontext "github.com/docker/distribution/context" "github.com/docker/distribution/manifest/ocischema" "github.com/opencontainers/go-digest" - "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) //ocischemaManifestHandler is a ManifestHandler that covers ocischema manifests. diff -Nru docker-registry-2.7.1+ds2/registry/storage/ocimanifesthandler_test.go docker-registry-2.8.0+ds1/registry/storage/ocimanifesthandler_test.go --- docker-registry-2.7.1+ds2/registry/storage/ocimanifesthandler_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/ocimanifesthandler_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -9,7 +9,7 @@ "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/ocischema" "github.com/docker/distribution/registry/storage/driver/inmemory" - "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) func TestVerifyOCIManifestNonDistributableLayer(t *testing.T) { diff -Nru docker-registry-2.7.1+ds2/registry/storage/paths.go docker-registry-2.8.0+ds1/registry/storage/paths.go --- docker-registry-2.7.1+ds2/registry/storage/paths.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/paths.go 2022-02-07 15:40:21.000000000 +0000 @@ -133,10 +133,7 @@ return path.Join(append(append(repoPrefix, v.name, "_manifests", "revisions"), components...)...), nil case manifestRevisionLinkPathSpec: - root, err := pathFor(manifestRevisionPathSpec{ - name: v.name, - revision: v.revision, - }) + root, err := pathFor(manifestRevisionPathSpec(v)) if err != nil { return "", err @@ -156,10 +153,7 @@ return path.Join(root, v.tag), nil case manifestTagCurrentPathSpec: - root, err := pathFor(manifestTagPathSpec{ - name: v.name, - tag: v.tag, - }) + root, err := pathFor(manifestTagPathSpec(v)) if err != nil { return "", err @@ -167,10 +161,7 @@ return path.Join(root, "current", "link"), nil case manifestTagIndexPathSpec: - root, err := pathFor(manifestTagPathSpec{ - name: v.name, - tag: v.tag, - }) + root, err := pathFor(manifestTagPathSpec(v)) if err != nil { return "", err @@ -178,11 +169,7 @@ return path.Join(root, "index"), nil case manifestTagIndexEntryLinkPathSpec: - root, err := pathFor(manifestTagIndexEntryPathSpec{ - name: v.name, - tag: v.tag, - revision: v.revision, - }) + root, err := pathFor(manifestTagIndexEntryPathSpec(v)) if err != nil { return "", err diff -Nru docker-registry-2.7.1+ds2/registry/storage/paths_test.go docker-registry-2.8.0+ds1/registry/storage/paths_test.go --- docker-registry-2.7.1+ds2/registry/storage/paths_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/paths_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -10,7 +10,6 @@ for _, testcase := range []struct { spec pathSpec expected string - err error }{ { spec: manifestRevisionPathSpec{ diff -Nru docker-registry-2.7.1+ds2/registry/storage/purgeuploads.go docker-registry-2.8.0+ds1/registry/storage/purgeuploads.go --- docker-registry-2.7.1+ds2/registry/storage/purgeuploads.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/purgeuploads.go 2022-02-07 15:40:21.000000000 +0000 @@ -59,7 +59,7 @@ // file, so gather files by UUID with a date from startedAt. func getOutstandingUploads(ctx context.Context, driver storageDriver.StorageDriver) (map[string]uploadData, []error) { var errors []error - uploads := make(map[string]uploadData, 0) + uploads := make(map[string]uploadData) inUploadDir := false root, err := pathFor(repositoriesRootPathSpec{}) diff -Nru docker-registry-2.7.1+ds2/registry/storage/purgeuploads_test.go docker-registry-2.8.0+ds1/registry/storage/purgeuploads_test.go --- docker-registry-2.7.1+ds2/registry/storage/purgeuploads_test.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/purgeuploads_test.go 2022-02-07 15:40:21.000000000 +0000 @@ -118,7 +118,7 @@ t.Fatalf(err.Error()) } nonUploadPath := strings.Replace(dataPath, "_upload", "_important", -1) - if strings.Index(nonUploadPath, "_upload") != -1 { + if strings.Contains(nonUploadPath, "_upload") { t.Fatalf("Non-upload path not created correctly") } @@ -132,7 +132,7 @@ t.Error("Unexpected errors", errs) } for _, file := range deleted { - if strings.Index(file, "_upload") == -1 { + if !strings.Contains(file, "_upload") { t.Errorf("Non-upload file deleted") } } diff -Nru docker-registry-2.7.1+ds2/registry/storage/schema2manifesthandler.go docker-registry-2.8.0+ds1/registry/storage/schema2manifesthandler.go --- docker-registry-2.7.1+ds2/registry/storage/schema2manifesthandler.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/schema2manifesthandler.go 2022-02-07 15:40:21.000000000 +0000 @@ -14,9 +14,8 @@ ) var ( - errUnexpectedURL = errors.New("unexpected URL on layer") - errMissingURL = errors.New("missing URL on layer") - errInvalidURL = errors.New("invalid URL on layer") + errMissingURL = errors.New("missing URL on layer") + errInvalidURL = errors.New("invalid URL on layer") ) //schema2ManifestHandler is a ManifestHandler that covers schema2 manifests. @@ -93,7 +92,7 @@ switch descriptor.MediaType { case schema2.MediaTypeForeignLayer: // Clients download this layer from an external URL, so do not check for - // its presense. + // its presence. if len(descriptor.URLs) == 0 { err = errMissingURL } diff -Nru docker-registry-2.7.1+ds2/registry/storage/tagstore.go docker-registry-2.8.0+ds1/registry/storage/tagstore.go --- docker-registry-2.7.1+ds2/registry/storage/tagstore.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/tagstore.go 2022-02-07 15:40:21.000000000 +0000 @@ -50,25 +50,6 @@ return tags, nil } -// exists returns true if the specified manifest tag exists in the repository. -func (ts *tagStore) exists(ctx context.Context, tag string) (bool, error) { - tagPath, err := pathFor(manifestTagCurrentPathSpec{ - name: ts.repository.Named().Name(), - tag: tag, - }) - - if err != nil { - return false, err - } - - exists, err := exists(ctx, ts.blobStore.driver, tagPath) - if err != nil { - return false, err - } - - return exists, nil -} - // Tag tags the digest with the given tag, updating the the store to point at // the current tag. The digest must point to a manifest. func (ts *tagStore) Tag(ctx context.Context, tag string, desc distribution.Descriptor) error { diff -Nru docker-registry-2.7.1+ds2/registry/storage/util.go docker-registry-2.8.0+ds1/registry/storage/util.go --- docker-registry-2.7.1+ds2/registry/storage/util.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/registry/storage/util.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -package storage - -import ( - "context" - - "github.com/docker/distribution/registry/storage/driver" -) - -// Exists provides a utility method to test whether or not a path exists in -// the given driver. -func exists(ctx context.Context, drv driver.StorageDriver, path string) (bool, error) { - if _, err := drv.Stat(ctx, path); err != nil { - switch err := err.(type) { - case driver.PathNotFoundError: - return false, nil - default: - return false, err - } - } - - return true, nil -} diff -Nru docker-registry-2.7.1+ds2/releases/v2.8.0.toml docker-registry-2.8.0+ds1/releases/v2.8.0.toml --- docker-registry-2.7.1+ds2/releases/v2.8.0.toml 1970-01-01 00:00:00.000000000 +0000 +++ docker-registry-2.8.0+ds1/releases/v2.8.0.toml 2022-02-07 15:40:21.000000000 +0000 @@ -0,0 +1,55 @@ +# commit to be tagged for new release +commit = "HEAD" + +project_name = "registry" +github_repo = "distribution/distribution" + +# previous release +previous = "v2.7.1" + +pre_release = false + +preface = """\ +The 2.8.0 registry release has been a long time overdue. +This is the last 2.x release. No further active development will continue on +2.x branch. Security vulnerability patches to 2.x might be considered, but +all active development will be focussed on v3 release due in 2022. +This release includes a security vulnerability fix along +with a few minor bug fixes and improvemnts in documentation and CI. + +See changelog below for full list of changes. + +### Bugfixes +* Close the io.ReadCloser from storage driver [#3370](https://github.com/distribution/distribution/pull/3370) +* Remove empty Content-Type header [#3297](https://github.com/distribution/distribution/pull/3297) +* Make ipfilteredby not required in cloudfront storage middleware [#3088](https://github.com/distribution/distribution/pull/3088) + +### Features +* Add reference.ParseDockerRef utility function [#3002](https://github.com/distribution/distribution/pull/3002) + +### CI build +* First draft of actions based ci [#3347](https://github.com/distribution/distribution/pull/3347) +* Fix vndr and check [#3001](https://github.com/distribution/distribution/pull/3001) +* Improve code quality by adding linter checks [#3385](https://github.com/distribution/distribution/pull/3385) + +### Documentation +* Add redirect for old URL [#3197](https://github.com/distribution/distribution/pull/3197) +* Fix broken table [#3073](https://github.com/distribution/distribution/pull/3073) +* Adding deprecated schema v1 instructions [#2987](https://github.com/distribution/distribution/pull/2987) +* Change should to must in v2 spec ([#3495](https://github.com/distribution/distribution/pull/3495)) + +### Storage drivers +* S3 Driver: add support for ceph radosgw [#3119](https://github.com/distribution/distribution/pull/3119) + +### Security +* Added flag for user configurable cipher suites [#3384](https://github.com/distribution/distribution/pull/3384) +* Address [CVE-2020-26160](https://github.com/advisories/GHSA-w73w-5m7g-f7qc) by replacing vulnerable third-party depedency[#3466](https://github.com/distribution/distribution/pull/3466) +* Replace math rand with crypto rand [#3531](https://github.com/distribution/distribution/pull/3531) +* Address [CVE-2021-41190](https://github.com/advisories/GHSA-mc8v-mgrf-8f4m) by validating document type before unmarshal [GHSA-77vh-xpmg-72qh](https://github.com/distribution/distribution-ghsa-qq97-vm5h-rrhg/pull/2) + +### Dependency Changes +* github.com/dgrijalva/jwt-go -> github.com/golang-jwt/jwt.git # v3.2.2 (a601269ab70c -> 4bbdd8ac624f) +* github.com/opencontainers/image-spec -> github.com/opencontainers/image-spec # v1.0.2 (ab7389ef9f50 -> 67d2d5658fe0) + +Previous release can be found at [v2.7.1](https://github.com/distribution/distribution/releases/tag/v2.7.1) +""" diff -Nru docker-registry-2.7.1+ds2/script/setup/install-dev-tools docker-registry-2.8.0+ds1/script/setup/install-dev-tools --- docker-registry-2.7.1+ds2/script/setup/install-dev-tools 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/script/setup/install-dev-tools 2022-02-07 15:40:21.000000000 +0000 @@ -1,11 +1,12 @@ #!/usr/bin/env bash +GOLANGCI_LINT_VERSION="v1.27.0" + # # Install developer tools to $GOBIN (or $GOPATH/bin if unset) # set -eu -o pipefail -go get -u github.com/alecthomas/gometalinter -gometalinter --install >/dev/null +cd /tmp go get -u github.com/LK4D4/vndr -go get -u github.com/cpuguy83/go-md2man +go get "github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_LINT_VERSION}" diff -Nru docker-registry-2.7.1+ds2/script/validate/dco docker-registry-2.8.0+ds1/script/validate/dco --- docker-registry-2.7.1+ds2/script/validate/dco 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/script/validate/dco 2022-02-07 15:40:21.000000000 +0000 @@ -9,4 +9,4 @@ fi verbosity="${DCO_VERBOSITY--v}" -GIT_CHECK_EXCLUDE="./vendor:./script/validate/template" git-validation "$verbosity" -run DCO,short-subject,dangling-whitespace +GIT_CHECK_EXCLUDE="./vendor:./script/validate/template" git-validation "$verbosity" -range "5b98226afefa11a06ef0c652af4995177c0efda0..HEAD" -run DCO,short-subject,dangling-whitespace \ No newline at end of file diff -Nru docker-registry-2.7.1+ds2/.travis.yml docker-registry-2.8.0+ds1/.travis.yml --- docker-registry-2.7.1+ds2/.travis.yml 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/.travis.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -dist: trusty -sudo: required -# setup travis so that we can run containers for integration tests -services: - - docker - -language: go - -go: - - "1.11.x" - -go_import_path: github.com/docker/distribution - -addons: - apt: - packages: - - python-minimal - - -env: - - TRAVIS_GOOS=linux DOCKER_BUILDTAGS="include_oss include_gcs" TRAVIS_CGO_ENABLED=1 - -before_install: - - uname -r - - sudo apt-get -q update - -install: - - go get -u github.com/vbatts/git-validation - # TODO: Add enforcement of license - # - go get -u github.com/kunalkushwaha/ltag - - cd $TRAVIS_BUILD_DIR - -script: - - export GOOS=$TRAVIS_GOOS - - export CGO_ENABLED=$TRAVIS_CGO_ENABLED - - DCO_VERBOSITY=-q script/validate/dco - - GOOS=linux script/setup/install-dev-tools - - script/validate/vendor - - go build -i . - - make check - - make build - - make binaries - # Currently takes too long - #- if [ "$GOOS" = "linux" ]; then make test-race ; fi - - if [ "$GOOS" = "linux" ]; then make coverage ; fi - -after_success: - - bash <(curl -s https://codecov.io/bash) -F linux - -before_deploy: - # Run tests with storage driver configurations diff -Nru docker-registry-2.7.1+ds2/vendor.conf docker-registry-2.8.0+ds1/vendor.conf --- docker-registry-2.7.1+ds2/vendor.conf 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/vendor.conf 2022-02-07 15:40:21.000000000 +0000 @@ -8,7 +8,7 @@ github.com/bugsnag/osext 0dd3f918b21bec95ace9dc86c7e70266cfc5c702 github.com/bugsnag/panicwrap e2c28503fcd0675329da73bf48b33404db873782 github.com/denverdino/aliyungo afedced274aa9a7fcdd47ac97018f0f8db4e5de2 -github.com/dgrijalva/jwt-go a601269ab70c205d26370c16f7c81e9017c14e04 +github.com/dgrijalva/jwt-go 4bbdd8ac624fc7a9ef7aec841c43d99b5fe65a29 https://github.com/golang-jwt/jwt.git # v3.2.2 github.com/docker/go-metrics 399ea8c73916000c64c2c76e8da00ca82f8387ab github.com/docker/libtrust fa567046d9b14f6aa788882a950d69651d230b21 github.com/garyburd/redigo 535138d7bcd717d6531c701ef5933d98b1866257 @@ -48,4 +48,4 @@ gopkg.in/yaml.v2 v2.2.1 rsc.io/letsencrypt e770c10b0f1a64775ae91d240407ce00d1a5bdeb https://github.com/dmcgowan/letsencrypt.git github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb -github.com/opencontainers/image-spec ab7389ef9f50030c9b245bc16b981c7ddf192882 +github.com/opencontainers/image-spec 67d2d5658fe0476ab9bf414cec164077ebff3920 # v1.0.2 diff -Nru docker-registry-2.7.1+ds2/version/version.go docker-registry-2.8.0+ds1/version/version.go --- docker-registry-2.7.1+ds2/version/version.go 2019-01-17 23:19:26.000000000 +0000 +++ docker-registry-2.8.0+ds1/version/version.go 2022-02-07 15:40:21.000000000 +0000 @@ -8,7 +8,7 @@ // the latest release tag by hand, always suffixed by "+unknown". During // build, it will be replaced by the actual version. The value here will be // used if the registry is run after a go get based install. -var Version = "v2.7.1+unknown" +var Version = "v2.8.0-beta.1+unknown" // Revision is filled with the VCS (e.g. git) revision being used to build // the program at linking time.