diff --git a/Makefile b/Makefile index c2992c598..6ac2911ca 100644 --- a/Makefile +++ b/Makefile @@ -26,16 +26,14 @@ $(PROTOC): null := space := $(null) # comma := , -# default to json1 for sqlite3 -TAGS := -tags=json1 +# default to json1 for sqlite3 and containers_image_openpgp for containers/image +TAGS := json1,containers_image_openpgp # Cluster to use for e2e testing CLUSTER ?= "" ifeq ($(CLUSTER), kind) # add kind to the list of tags -TAGS += kind -# convert tag format from space to comma list -TAGS := $(subst $(space),$(comma),$(strip $(TAGS))) +TAGS := $(TAGS),kind endif # -race is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64, darwin/amd64 and windows/amd64 @@ -49,12 +47,12 @@ endif all: clean test build $(CMDS): - $(extra_env) $(GO) build $(extra_flags) $(TAGS) -o $@ ./cmd/$(notdir $@) + $(extra_env) $(GO) build $(extra_flags) -tags=$(TAGS) -o $@ ./cmd/$(notdir $@) .PHONY: $(OPM) $(OPM): opm_version_flags=-ldflags "-X '$(PKG)/cmd/opm/version.gitCommit=$(GIT_COMMIT)' -X '$(PKG)/cmd/opm/version.opmVersion=$(OPM_VERSION)' -X '$(PKG)/cmd/opm/version.buildDate=$(BUILD_DATE)'" $(OPM): - $(extra_env) $(GO) build $(opm_version_flags) $(extra_flags) $(TAGS) -o $@ ./cmd/$(notdir $@) + $(extra_env) $(GO) build $(opm_version_flags) $(extra_flags) -tags=$(TAGS) -o $@ ./cmd/$(notdir $@) .PHONY: build build: clean $(CMDS) $(OPM) @@ -63,8 +61,8 @@ build: clean $(CMDS) $(OPM) cross: opm_version_flags=-ldflags "-X '$(PKG)/cmd/opm/version.gitCommit=$(GIT_COMMIT)' -X '$(PKG)/cmd/opm/version.opmVersion=$(OPM_VERSION)' -X '$(PKG)/cmd/opm/version.buildDate=$(BUILD_DATE)'" cross: ifeq ($(shell go env GOARCH),amd64) - GOOS=darwin CC=o64-clang CXX=o64-clang++ CGO_ENABLED=1 $(GO) build $(opm_version_flags) $(TAGS) -o "bin/darwin-amd64-opm" --ldflags "-extld=o64-clang" ./cmd/opm - GOOS=windows CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ CGO_ENABLED=1 $(GO) build $(opm_version_flags) $(TAGS) -o "bin/windows-amd64-opm" --ldflags "-extld=x86_64-w64-mingw32-gcc" -buildmode=exe ./cmd/opm + GOOS=darwin CC=o64-clang CXX=o64-clang++ CGO_ENABLED=1 $(GO) build $(opm_version_flags) -tags=$(TAGS) -o "bin/darwin-amd64-opm" --ldflags "-extld=o64-clang" ./cmd/opm + GOOS=windows CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ CGO_ENABLED=1 $(GO) build $(opm_version_flags) -tags=$(TAGS) -o "bin/windows-amd64-opm" --ldflags "-extld=x86_64-w64-mingw32-gcc" -buildmode=exe ./cmd/opm endif .PHONY: static @@ -73,7 +71,7 @@ static: build .PHONY: unit unit: - $(GO) test -coverprofile=coverage.out $(SPECIFIC_UNIT_TEST) $(SPECIFIC_SKIP_UNIT_TEST) $(TAGS) $(TEST_RACE) -count=1 ./pkg/... ./alpha/... + $(GO) test -coverprofile=coverage.out --coverpkg=./... $(SPECIFIC_UNIT_TEST) $(SPECIFIC_SKIP_UNIT_TEST) -tags=$(TAGS) $(TEST_RACE) -count=1 ./pkg/... ./alpha/... .PHONY: tidy tidy: @@ -102,10 +100,8 @@ image-upstream: docker build -f upstream-example.Dockerfile . .PHONY: lint -#lint: -# find . -type f -name '*.go' ! -name '*.pb.go' -print0 | xargs -0 goimports -w lint: $(GOLANGCI_LINT) - $(GOLANGCI_LINT) run $(GOLANGCI_LINT_ARGS) + $(GOLANGCI_LINT) run --build-tags=$(TAGS) $(GOLANGCI_LINT_ARGS) .PHONY: fix-lint fix-lint: $(GOLANGCI_LINT) @@ -133,7 +129,7 @@ clean: .PHONY: e2e e2e: $(GINKGO) - $(GINKGO) --v --randomize-all --progress --trace --randomize-suites --race $(if $(TEST),-focus '$(TEST)') $(TAGS) ./test/e2e -- $(if $(SKIPTLS),-skip-tls-verify true) $(if $(USEHTTP),-use-http true) + $(GINKGO) --v --randomize-all --progress --trace --randomize-suites --race $(if $(TEST),-focus '$(TEST)') -tags=$(TAGS) ./test/e2e -- $(if $(SKIPTLS),-skip-tls-verify true) $(if $(USEHTTP),-use-http true) .PHONY: release export OPM_IMAGE_REPO ?= quay.io/operator-framework/opm diff --git a/alpha/action/render.go b/alpha/action/render.go index ad7a066b4..a124c0f8a 100644 --- a/alpha/action/render.go +++ b/alpha/action/render.go @@ -22,9 +22,8 @@ import ( "github.com/operator-framework/operator-registry/alpha/property" "github.com/operator-framework/operator-registry/pkg/containertools" "github.com/operator-framework/operator-registry/pkg/image" - "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" + "github.com/operator-framework/operator-registry/pkg/image/containersimageregistry" "github.com/operator-framework/operator-registry/pkg/lib/bundle" - "github.com/operator-framework/operator-registry/pkg/lib/log" "github.com/operator-framework/operator-registry/pkg/registry" "github.com/operator-framework/operator-registry/pkg/sqlite" ) @@ -66,7 +65,7 @@ func (r Render) Run(ctx context.Context) (*declcfg.DeclarativeConfig, error) { logDeprecationMessage.Do(func() {}) } if r.Registry == nil { - reg, err := r.createRegistry() + reg, err := containersimageregistry.NewDefault() if err != nil { return nil, fmt.Errorf("create registry: %v", err) } @@ -101,26 +100,6 @@ func (r Render) Run(ctx context.Context) (*declcfg.DeclarativeConfig, error) { return combineConfigs(cfgs), nil } -func (r Render) createRegistry() (*containerdregistry.Registry, error) { - cacheDir, err := os.MkdirTemp("", "render-registry-") - if err != nil { - return nil, fmt.Errorf("create tempdir: %v", err) - } - - reg, err := containerdregistry.NewRegistry( - containerdregistry.WithCacheDir(cacheDir), - - // The containerd registry impl is somewhat verbose, even on the happy path, - // so discard all logger logs. Any important failures will be returned from - // registry methods and eventually logged as fatal errors. - containerdregistry.WithLog(log.Null()), - ) - if err != nil { - return nil, err - } - return reg, nil -} - func (r Render) renderReference(ctx context.Context, ref string) (*declcfg.DeclarativeConfig, error) { stat, err := os.Stat(ref) if err != nil { diff --git a/cmd/opm/alpha/bundle/validate.go b/cmd/opm/alpha/bundle/validate.go index c1044c05c..069cfff9e 100644 --- a/cmd/opm/alpha/bundle/validate.go +++ b/cmd/opm/alpha/bundle/validate.go @@ -10,7 +10,7 @@ import ( "github.com/operator-framework/operator-registry/pkg/containertools" "github.com/operator-framework/operator-registry/pkg/image" - "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" + "github.com/operator-framework/operator-registry/pkg/image/containersimageregistry" "github.com/operator-framework/operator-registry/pkg/image/execregistry" "github.com/operator-framework/operator-registry/pkg/lib/bundle" ) @@ -69,7 +69,7 @@ func validateFunc(cmd *cobra.Command, _ []string) error { case containertools.PodmanTool, containertools.DockerTool: registry, err = execregistry.NewRegistry(tool, logger) case containertools.NoneTool: - registry, err = containerdregistry.NewRegistry(containerdregistry.WithLog(logger)) + registry, err = containersimageregistry.NewDefault() default: err = fmt.Errorf("unrecognized container-tool option: %s", containerTool) } diff --git a/cmd/opm/internal/util/util.go b/cmd/opm/internal/util/util.go index e007caa48..35455b85b 100644 --- a/cmd/opm/internal/util/util.go +++ b/cmd/opm/internal/util/util.go @@ -7,8 +7,8 @@ import ( "github.com/spf13/cobra" - "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" - "github.com/operator-framework/operator-registry/pkg/lib/log" + "github.com/operator-framework/operator-registry/pkg/image" + "github.com/operator-framework/operator-registry/pkg/image/containersimageregistry" ) // GetTLSOptions validates and returns TLS options set by opm flags @@ -45,27 +45,15 @@ func GetTLSOptions(cmd *cobra.Command) (bool, bool, error) { // This works in tandem with opm/index/cmd, which adds the relevant flags as persistent // as part of the root command (cmd/root/cmd) initialization -func CreateCLIRegistry(cmd *cobra.Command) (*containerdregistry.Registry, error) { +func CreateCLIRegistry(cmd *cobra.Command) (image.Registry, error) { skipTLSVerify, useHTTP, err := GetTLSOptions(cmd) if err != nil { return nil, err } - - cacheDir, err := os.MkdirTemp("", "opm-registry-") - if err != nil { - return nil, err - } - - reg, err := containerdregistry.NewRegistry( - containerdregistry.WithCacheDir(cacheDir), - containerdregistry.SkipTLSVerify(skipTLSVerify), - containerdregistry.WithPlainHTTP(useHTTP), - containerdregistry.WithLog(log.Null()), + return containersimageregistry.New( + containersimageregistry.DefaultSystemContext, + containersimageregistry.WithInsecureSkipTLSVerify(skipTLSVerify || useHTTP), ) - if err != nil { - return nil, err - } - return reg, nil } func OpenFileOrStdin(cmd *cobra.Command, args []string) (io.ReadCloser, string, error) { diff --git a/go.mod b/go.mod index ec5337a7a..f06a69ab4 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,6 @@ require ( github.com/opencontainers/image-spec v1.1.1 github.com/operator-framework/api v0.30.0 github.com/otiai10/copy v1.14.1 - github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.9.1 @@ -51,6 +50,7 @@ require ( k8s.io/apimachinery v0.32.3 k8s.io/client-go v0.32.3 k8s.io/kubectl v0.32.0 + oras.land/oras-go/v2 v2.5.0 sigs.k8s.io/controller-runtime v0.20.4 sigs.k8s.io/kind v0.27.0 sigs.k8s.io/yaml v1.4.0 @@ -65,10 +65,11 @@ require ( github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/hcsshim v0.12.9 // indirect + github.com/VividCortex/ewma v1.2.0 // indirect + github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/containerd/cgroups/v3 v3.0.5 // indirect @@ -82,7 +83,7 @@ require ( github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect github.com/containers/ocicrypt v1.2.1 // indirect github.com/containers/storage v1.58.0 // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/docker/distribution v2.8.3+incompatible // indirect @@ -102,15 +103,23 @@ require ( github.com/go-jose/go-jose/v4 v4.0.5 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/analysis v0.23.0 // indirect + github.com/go-openapi/errors v0.22.1 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/loads v0.22.0 // indirect + github.com/go-openapi/runtime v0.28.0 // indirect + github.com/go-openapi/spec v0.21.0 // indirect + github.com/go-openapi/strfmt v0.23.0 // indirect github.com/go-openapi/swag v0.23.1 // indirect + github.com/go-openapi/validate v0.24.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/cel-go v0.22.1 // indirect github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-containerregistry v0.20.3 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect @@ -118,7 +127,7 @@ require ( github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -126,10 +135,15 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/pgzip v1.2.6 // indirect + github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.9.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/miekg/pkcs11 v1.1.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/locker v1.0.1 // indirect github.com/moby/spdystream v0.5.0 // indirect github.com/moby/sys/capability v0.4.0 // indirect @@ -142,10 +156,12 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect + github.com/oklog/ulid v1.3.1 // indirect github.com/opencontainers/runtime-spec v1.2.1 // indirect github.com/otiai10/mint v1.6.3 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/proglottis/gpgme v0.1.4 // indirect github.com/prometheus/client_golang v1.21.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.62.0 // indirect @@ -153,11 +169,24 @@ require ( github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect github.com/redis/go-redis/v9 v9.7.3 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect + github.com/sigstore/fulcio v1.6.6 // indirect + github.com/sigstore/protobuf-specs v0.4.1 // indirect + github.com/sigstore/rekor v1.3.10 // indirect + github.com/sigstore/sigstore v1.9.3 // indirect + github.com/smallstep/pkcs7 v0.1.1 // indirect github.com/spiffe/go-spiffe/v2 v2.4.0 // indirect + github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect + github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect + github.com/ulikunitz/xz v0.5.12 // indirect + github.com/vbatts/tar-split v0.12.1 // indirect + github.com/vbauerster/mpb/v8 v8.9.3 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/zeebo/errs v1.3.0 // indirect + go.mongodb.org/mongo-driver v1.14.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 // indirect @@ -170,7 +199,7 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.54.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0 // indirect @@ -186,9 +215,9 @@ require ( golang.org/x/crypto v0.37.0 // indirect golang.org/x/oauth2 v0.29.0 // indirect golang.org/x/term v0.31.0 // indirect - golang.org/x/time v0.7.0 // indirect + golang.org/x/time v0.11.0 // indirect golang.org/x/tools v0.31.0 // indirect - google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect diff --git a/go.sum b/go.sum index 4897fb488..38535c199 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ al.essio.dev/pkg/shellescape v1.5.1/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWt cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4= cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= @@ -16,6 +18,10 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg= github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y= +github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= +github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= +github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= +github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/akrylysov/pogreb v0.10.2 h1:e6PxmeyEhWyi2AKOBIJzAEi4HkiC+lKyCocRGlnDi78= github.com/akrylysov/pogreb v0.10.2/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -32,8 +38,6 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= -github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= @@ -85,6 +89,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 h1:uX1JmpONuD549D73r6cgnxyUu18Zb7yHAy5AYU0Pm4Q= +github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -141,16 +147,31 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= +github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= +github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= +github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU= +github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco= +github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs= +github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ= +github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= +github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= +github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= +github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= +github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= +github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= +github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -188,8 +209,11 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI= +github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -210,10 +234,10 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.2.0 h1:kQ0NI7W1B3HwiN5gAYtY+XFItDPbLBwYRxAqbFTyDes= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.2.0/go.mod h1:zrT2dxOAjNFPRGjTUe2Xmb4q4YdUwVvQFV6xiCSf+z0= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99 h1:JYghRBlGCZyCF2wNUJ8W0cwaQdtpcssJ4CgC406g+WU= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= github.com/grpc-ecosystem/grpc-health-probe v0.4.37 h1:x8IIa8JfqiXpBX3xtmm3jz5b9YMq4Lpc9/b+ZAfzRZI= github.com/grpc-ecosystem/grpc-health-probe v0.4.37/go.mod h1:uKUtQKoBUvaI4Ez1jaLCHxFYYYoYn/FYkqNgl+8hADw= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= @@ -232,6 +256,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jmhodges/clock v1.2.0 h1:eq4kys+NI0PLngzaHEe7AmPT90XMGIEySD1JfV1PDIs= +github.com/jmhodges/clock v1.2.0/go.mod h1:qKjhA7x7u/lQpPB1XAqX1b1lCI/w3/fNuYpI/ZjLynI= github.com/joelanford/ignore v0.1.1 h1:vKky5RDoPT+WbONrbQBgOn95VV/UPh4ejlyAbbzgnQk= github.com/joelanford/ignore v0.1.1/go.mod h1:8eho/D8fwQ3rIXrLwE23AaeaGDNXqLE9QJ3zJ4LIPCw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -255,6 +281,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec h1:2tTW6cDth2TSgRbAhD7yjZzTQmcN25sDRPEeinR51yQ= +github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec/go.mod h1:TmwEoGCwIti7BCeJ9hescZgRtatxRE+A72pCoPfmcfk= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= @@ -263,13 +291,19 @@ github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4 github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A= github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/maxbrunsfeld/counterfeiter/v6 v6.11.2 h1:yVCLo4+ACVroOEr4iFU1iH46Ldlzz2rTuu18Ra7M8sU= github.com/maxbrunsfeld/counterfeiter/v6 v6.11.2/go.mod h1:VzB2VoMh1Y32/QqDfg9ZJYHj99oM4LiGtqPZydTiQSQ= +github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= +github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= @@ -298,6 +332,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= @@ -316,8 +352,6 @@ github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= -github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -326,6 +360,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/proglottis/gpgme v0.1.4 h1:3nE7YNA70o2aLjcg63tXMOhPD7bplfE5CBdV+hLAm2M= +github.com/proglottis/gpgme v0.1.4/go.mod h1:5LoXMgpE4bttgwwdv9bLs/vwqv3qV7F4glEEZ7mRKrM= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= @@ -352,21 +388,40 @@ github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnA github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= +github.com/secure-systems-lab/go-securesystemslib v0.9.0 h1:rf1HIbL64nUpEIZnjLZ3mcNEL9NBPB0iuVjyxvq3LZc= +github.com/secure-systems-lab/go-securesystemslib v0.9.0/go.mod h1:DVHKMcZ+V4/woA/peqr+L0joiRXbPpQ042GgJckkFgw= +github.com/sigstore/fulcio v1.6.6 h1:XaMYX6TNT+8n7Npe8D94nyZ7/ERjEsNGFC+REdi/wzw= +github.com/sigstore/fulcio v1.6.6/go.mod h1:BhQ22lwaebDgIxVBEYOOqLRcN5+xOV+C9bh/GUXRhOk= +github.com/sigstore/protobuf-specs v0.4.1 h1:5SsMqZbdkcO/DNHudaxuCUEjj6x29tS2Xby1BxGU7Zc= +github.com/sigstore/protobuf-specs v0.4.1/go.mod h1:+gXR+38nIa2oEupqDdzg4qSBT0Os+sP7oYv6alWewWc= +github.com/sigstore/rekor v1.3.10 h1:/mSvRo4MZ/59ECIlARhyykAlQlkmeAQpvBPlmJtZOCU= +github.com/sigstore/rekor v1.3.10/go.mod h1:JvryKJ40O0XA48MdzYUPu0y4fyvqt0C4iSY7ri9iu3A= +github.com/sigstore/sigstore v1.9.3 h1:y2qlTj+vh+Or3ictKuR3JUFawZPdDxAjrWkeFhon0OQ= +github.com/sigstore/sigstore v1.9.3/go.mod h1:VwYkiw0G0dRtwL25KSs04hCyVFF6CYMd/qvNeYrl7EQ= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/smallstep/pkcs7 v0.1.1 h1:x+rPdt2W088V9Vkjho4KtoggyktZJlMduZAtRHm68LU= +github.com/smallstep/pkcs7 v0.1.1/go.mod h1:dL6j5AIz9GHjVEBTXtW+QliALcgM19RtXaTeyxI+AfA= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spiffe/go-spiffe/v2 v2.4.0 h1:j/FynG7hi2azrBG5cvjRcnQ4sux/VNj8FAVc99Fl66c= github.com/spiffe/go-spiffe/v2 v2.4.0/go.mod h1:m5qJ1hGzjxjtrkGHZupoXHo/FDWwCB1MdSyBzfHugx0= +github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw= +github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6/go.mod h1:39R/xuhNgVhi+K0/zst4TLrJrVmbm6LVgl4A0+ZFS5M= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -383,15 +438,20 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0= +github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs= github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo= github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= +github.com/vbauerster/mpb/v8 v8.9.3 h1:PnMeF+sMvYv9u23l6DO6Q3+Mdj408mjLRXIzmUmU2Z8= +github.com/vbauerster/mpb/v8 v8.9.3/go.mod h1:hxS8Hz4C6ijnppDSIX6LjG8FYJSoPo9iIOcE53Zik0c= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs= github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk= @@ -402,6 +462,8 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.16 h1:ZgY48uH6UvB+/7R9Yf4x574uCO3jIx0TRDyetSf go.etcd.io/etcd/client/pkg/v3 v3.5.16/go.mod h1:V8acl8pcEK0Y2g19YlOV9m9ssUe6MgiDSobSoaBAM0E= go.etcd.io/etcd/client/v3 v3.5.16 h1:sSmVYOAHeC9doqi0gv7v86oY/BTld0SEFGaxsU9eRhE= go.etcd.io/etcd/client/v3 v3.5.16/go.mod h1:X+rExSGkyqxvu276cr2OwPLBaeqFu1cIl4vmRjAD/50= +go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= +go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= @@ -410,8 +472,8 @@ go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 h1:UW0+QyeyBVhn+COBec3nGh go.opentelemetry.io/contrib/bridges/prometheus v0.57.0/go.mod h1:ppciCHRLsyCio54qbzQv0E4Jyth/fLWDTJYfvWpcSVk= go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 h1:jmTVJ86dP60C01K3slFQa2NQ/Aoi7zA+wy7vMOKD9H4= go.opentelemetry.io/contrib/exporters/autoexport v0.57.0/go.mod h1:EJBheUMttD/lABFyLXhce47Wr6DPWYReCzaZiXadH7g= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= @@ -428,8 +490,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 h1:cMyu9O88joYEaI47CnQkxO1XZdpoTF9fEnW2duIddhw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0/go.mod h1:6Am3rn7P9TVVeXYG+wtcGE7IE1tsQ+bP3AuWcKt/gOI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0= go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU= go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 h1:CHXNXwfKWfzS65yrlB2PVds1IBZcdsX8Vepy9of0iRU= @@ -466,6 +528,11 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -477,6 +544,11 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -490,7 +562,14 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -503,6 +582,12 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -515,20 +600,44 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -538,6 +647,10 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -549,8 +662,8 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU= -google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4= +google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE= +google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c= @@ -617,6 +730,8 @@ k8s.io/kubectl v0.32.0 h1:rpxl+ng9qeG79YA4Em9tLSfX0G8W0vfaiPVrc/WR7Xw= k8s.io/kubectl v0.32.0/go.mod h1:qIjSX+QgPQUgdy8ps6eKsYNF+YmFOAO3WygfucIqFiE= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c= +oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 h1:CPT0ExVicCzcpeN4baWEV2ko2Z/AsiZgEdwgcfwLgMo= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= diff --git a/internal/testutil/image/registry.go b/internal/testutil/image/registry.go new file mode 100644 index 000000000..736cb003d --- /dev/null +++ b/internal/testutil/image/registry.go @@ -0,0 +1,35 @@ +package image + +import ( + "context" + "net/http" + "net/http/httptest" + + "github.com/distribution/distribution/v3/configuration" + "github.com/distribution/distribution/v3/registry/handlers" + _ "github.com/distribution/distribution/v3/registry/storage/driver/filesystem" // Driver for persisting docker image data to the filesystem. + _ "github.com/distribution/distribution/v3/registry/storage/driver/inmemory" // Driver for keeping docker image data in memory. +) + +// RunDockerRegistry runs a docker registry on an available port and returns its host string if successful, otherwise it returns an error. +// If the rootDir argument isn't empty, the registry is configured to use this as the root directory for persisting image data to the filesystem. +// If the rootDir argument is empty, the registry is configured to keep image data in memory. +func RunDockerRegistry(ctx context.Context, rootDir string, middlewares ...func(http.Handler) http.Handler) *httptest.Server { + config := &configuration.Configuration{} + config.Log.Level = "error" + + if rootDir != "" { + config.Storage = map[string]configuration.Parameters{"filesystem": map[string]interface{}{ + "rootdirectory": rootDir, + }} + } else { + config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}} + } + + var dockerRegistryApp http.Handler = handlers.NewApp(ctx, config) + for _, m := range middlewares { + dockerRegistryApp = m(dockerRegistryApp) + } + server := httptest.NewTLSServer(dockerRegistryApp) + return server +} diff --git a/pkg/image/containersimageregistry/registry.go b/pkg/image/containersimageregistry/registry.go new file mode 100644 index 000000000..f3452106d --- /dev/null +++ b/pkg/image/containersimageregistry/registry.go @@ -0,0 +1,287 @@ +package containersimageregistry + +import ( + "archive/tar" + "context" + "fmt" + "os" + "path/filepath" + + "github.com/containerd/containerd/archive" + "github.com/containers/common/pkg/auth" + "github.com/containers/image/v5/copy" + "github.com/containers/image/v5/docker" + "github.com/containers/image/v5/docker/reference" + "github.com/containers/image/v5/image" + "github.com/containers/image/v5/oci/layout" + "github.com/containers/image/v5/pkg/compression" + "github.com/containers/image/v5/pkg/docker/config" + "github.com/containers/image/v5/signature" + "github.com/containers/image/v5/types" + dockerconfig "github.com/docker/cli/cli/config" + "oras.land/oras-go/v2/content/oci" + + orimage "github.com/operator-framework/operator-registry/pkg/image" +) + +var _ orimage.Registry = (*Registry)(nil) + +type Registry struct { + sourceCtx *types.SystemContext + cache *cacheConfig +} + +var DefaultSystemContext = &types.SystemContext{OSChoice: "linux"} + +func New(sourceCtx *types.SystemContext, opts ...Option) (orimage.Registry, error) { + if sourceCtx == nil { + sourceCtx = &types.SystemContext{} + } + reg := &Registry{ + sourceCtx: sourceCtx, + } + + for _, opt := range opts { + if err := opt(reg); err != nil { + return nil, err + } + } + + if reg.cache == nil { + var err error + reg.cache, err = getDefaultImageCache() + if err != nil { + return nil, err + } + } + + return reg, nil +} + +func NewDefault() (orimage.Registry, error) { + return New(DefaultSystemContext) +} + +type cacheConfig struct { + baseDir string + preserve bool +} + +func (c *cacheConfig) ociLayoutDir() string { + return filepath.Join(c.baseDir, "oci-layout") +} +func (c *cacheConfig) blobInfoCacheDir() string { + return filepath.Join(c.baseDir, "blob-info-cache") +} + +func (c *cacheConfig) getSystemContext() *types.SystemContext { + return &types.SystemContext{ + BlobInfoCacheDir: c.blobInfoCacheDir(), + } +} + +type Option func(*Registry) error + +func getDefaultImageCache() (*cacheConfig, error) { + if dir := os.Getenv("OLM_CACHE_DIR"); dir != "" { + return newCacheConfig(filepath.Join(dir, "images"), true), nil + } + return getTemporaryImageCache() +} + +func getTemporaryImageCache() (*cacheConfig, error) { + tmpDir, err := os.MkdirTemp("", "opm-containers-image-cache-") + if err != nil { + return nil, err + } + return newCacheConfig(tmpDir, false), nil +} + +func newCacheConfig(dir string, preserve bool) *cacheConfig { + return &cacheConfig{ + baseDir: dir, + preserve: preserve, + } +} + +func WithTemporaryImageCache() Option { + return func(r *Registry) error { + var err error + r.cache, err = getTemporaryImageCache() + if err != nil { + return err + } + return nil + } +} + +func WithInsecureSkipTLSVerify(insecureSkipTLSVerify bool) Option { + return func(r *Registry) error { + r.sourceCtx.DockerDaemonInsecureSkipTLSVerify = insecureSkipTLSVerify + r.sourceCtx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(insecureSkipTLSVerify) + r.sourceCtx.OCIInsecureSkipTLSVerify = insecureSkipTLSVerify + return nil + } +} + +func (r *Registry) Pull(ctx context.Context, ref orimage.Reference) error { + namedRef, err := reference.ParseNamed(ref.String()) + if err != nil { + return err + } + dockerRef, err := docker.NewReference(namedRef) + if err != nil { + return err + } + + if err := os.MkdirAll(r.cache.ociLayoutDir(), 0700); err != nil { + return err + } + ociLayoutRef, err := layout.NewReference(r.cache.ociLayoutDir(), ref.String()) + if err != nil { + return err + } + + policy, err := signature.DefaultPolicy(r.sourceCtx) + if err != nil { + return err + } + policyContext, err := signature.NewPolicyContext(policy) + if err != nil { + return err + } + + sourceCtx := r.sourceCtx + authFile := getAuthFile(r.sourceCtx, namedRef.String()) + if authFile != "" { + sourceCtx.AuthFilePath = authFile + } + + if _, err := copy.Image(ctx, policyContext, ociLayoutRef, dockerRef, ©.Options{ + SourceCtx: sourceCtx, + DestinationCtx: r.cache.getSystemContext(), + OptimizeDestinationImageAlreadyExists: true, + }); err != nil { + return err + } + return nil +} + +func (r *Registry) Unpack(ctx context.Context, ref orimage.Reference, unpackDir string) error { + ociLayoutRef, err := layout.NewReference(r.cache.ociLayoutDir(), ref.String()) + if err != nil { + return fmt.Errorf("could not create oci layout reference: %w", err) + } + + ociLayoutCtx := r.cache.getSystemContext() + imageSource, err := ociLayoutRef.NewImageSource(ctx, ociLayoutCtx) + if err != nil { + return fmt.Errorf("failed to create oci image source: %v", err) + } + defer imageSource.Close() + + img, err := image.FromSource(ctx, ociLayoutCtx, imageSource) + if err != nil { + return fmt.Errorf("could not get image from oci image source: %v", err) + } + + if err := os.MkdirAll(unpackDir, 0700); err != nil { + return err + } + + for _, info := range img.LayerInfos() { + if err := func() error { + layer, _, err := imageSource.GetBlob(ctx, info, nil) + if err != nil { + return fmt.Errorf("failed to get blob: %v", err) + } + defer layer.Close() + + decompressed, _, err := compression.AutoDecompress(layer) + if err != nil { + return fmt.Errorf("failed to decompress layer: %v", err) + } + + if _, err := archive.Apply(ctx, unpackDir, decompressed, archive.WithFilter(func(th *tar.Header) (bool, error) { + th.PAXRecords = nil + th.Xattrs = nil //nolint:staticcheck + th.Uid = os.Getuid() + th.Gid = os.Getgid() + th.Mode = 0600 + if th.FileInfo().IsDir() { + th.Mode = 0700 + } + return true, nil + })); err != nil { + return fmt.Errorf("failed to apply layer: %v", err) + } + return nil + }(); err != nil { + return err + } + } + return nil +} + +func (r *Registry) Labels(ctx context.Context, ref orimage.Reference) (map[string]string, error) { + ociLayoutRef, err := layout.NewReference(r.cache.ociLayoutDir(), ref.String()) + if err != nil { + return nil, fmt.Errorf("could not create oci layout reference: %w", err) + } + + ociLayoutCtx := r.cache.getSystemContext() + img, err := ociLayoutRef.NewImage(ctx, ociLayoutCtx) + if err != nil { + return nil, fmt.Errorf("could not load image from oci image reference: %v", err) + } + imgConfig, err := img.OCIConfig(ctx) + if err != nil { + return nil, fmt.Errorf("could not get oci config from image: %v", err) + } + return imgConfig.Config.Labels, nil +} + +func (r *Registry) Destroy() error { + if !r.cache.preserve { + return os.RemoveAll(r.cache.baseDir) + } + + store, err := oci.NewWithContext(context.TODO(), r.cache.ociLayoutDir()) + if err != nil { + return fmt.Errorf("open cache for garbage collection: %v", err) + } + if err := store.GC(context.TODO()); err != nil { + return fmt.Errorf("garbage collection failed: %v", err) + } + return nil +} + +// This is a slight variation on the auth.GetDefaultAuthFile function provided by containers/image. +// The reason for this variation is so that this image registry implementation can be used as a drop-in +// replacement for our existing containerd-based image registry client, and remain compatible with current +// behavior. +func getAuthFile(sourceCtx *types.SystemContext, ref string) string { + // By default, we will use the docker config file in the standard docker config directory. + // However, if REGISTRY_AUTH_FILE or DOCKER_CONFIG environment variables are set, we will + // use those (in that order) instead to derive the auth config file. + authFile := filepath.Join(dockerconfig.Dir(), dockerconfig.ConfigFileName) + if defaultAuthFile := auth.GetDefaultAuthFile(); defaultAuthFile != "" { + authFile = defaultAuthFile + } + + // In order to maintain backward-compatibility with the original credential getter from + // the containerd registry implementation, we will first try to get the credentials from + // the auth config file we derived above, if it exists. If we find a matching credential + // in this file, we'll use this file. + if stat, statErr := os.Stat(authFile); statErr == nil && stat.Mode().IsRegular() { + if _, err := config.GetCredentials(&types.SystemContext{AuthFilePath: authFile}, ref); err == nil { + return authFile + } + } + // If the auth file was unset, doesn't exist, or if we couldn't find credentials in it, + // we'll use system defaults from containers/image (podman/skopeo) to lookup the credentials. + if sourceCtx != nil && sourceCtx.AuthFilePath != "" { + return sourceCtx.AuthFilePath + } + return "" +} diff --git a/pkg/image/registry_test.go b/pkg/image/registry_test.go index ac1df7ca4..4fc638c8f 100644 --- a/pkg/image/registry_test.go +++ b/pkg/image/registry_test.go @@ -4,53 +4,83 @@ import ( "context" "crypto/rand" "crypto/x509" + "encoding/pem" "errors" "fmt" "io" "math" "math/big" "net/http" + "net/url" "os" + "path/filepath" "sync" "testing" - distribution "github.com/distribution/distribution/v3" - "github.com/distribution/distribution/v3/configuration" - repositorymiddleware "github.com/distribution/distribution/v3/registry/middleware/repository" + "github.com/containers/image/v5/types" + "github.com/distribution/distribution/v3" "github.com/distribution/reference" "github.com/opencontainers/go-digest" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" "golang.org/x/mod/sumdb/dirhash" + libimage "github.com/operator-framework/operator-registry/internal/testutil/image" "github.com/operator-framework/operator-registry/pkg/image" "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" - libimage "github.com/operator-framework/operator-registry/pkg/lib/image" + "github.com/operator-framework/operator-registry/pkg/image/containersimageregistry" ) // cleanupFunc is a function that cleans up after some test infra. type cleanupFunc func() // newRegistryFunc is a function that creates and returns a new image.Registry to test its cleanupFunc. -type newRegistryFunc func(t *testing.T, cafile string) (image.Registry, cleanupFunc) +type newRegistryFunc func(t *testing.T, serverCert *x509.Certificate) (image.Registry, cleanupFunc) -func poolForCertFile(t *testing.T, file string) *x509.CertPool { - rootCAs := x509.NewCertPool() - certs, err := os.ReadFile(file) +func caDirForCert(t *testing.T, serverCert *x509.Certificate) string { + caDir, err := os.MkdirTemp("", "opm-registry-test-ca-") + require.NoError(t, err) + caFile, err := os.Create(filepath.Join(caDir, "ca.crt")) require.NoError(t, err) - require.True(t, rootCAs.AppendCertsFromPEM(certs)) + + require.NoError(t, pem.Encode(caFile, &pem.Block{ + Type: "CERTIFICATE", + Bytes: serverCert.Raw, + })) + require.NoError(t, caFile.Close()) + return caDir +} + +func poolForCert(serverCert *x509.Certificate) *x509.CertPool { + rootCAs := x509.NewCertPool() + rootCAs.AddCert(serverCert) return rootCAs } func TestRegistries(t *testing.T) { registries := map[string]newRegistryFunc{ - "containerd": func(t *testing.T, cafile string) (image.Registry, cleanupFunc) { + "containersimage": func(t *testing.T, serverCert *x509.Certificate) (image.Registry, cleanupFunc) { + caDir := caDirForCert(t, serverCert) + sourceCtx := &types.SystemContext{ + OCICertPath: caDir, + DockerCertPath: caDir, + DockerPerHostCertDirPath: caDir, + } + r, err := containersimageregistry.New(sourceCtx, containersimageregistry.WithTemporaryImageCache()) + require.NoError(t, err) + cleanup := func() { + require.NoError(t, os.RemoveAll(caDir)) + require.NoError(t, r.Destroy()) + } + return r, cleanup + }, + "containerd": func(t *testing.T, serverCert *x509.Certificate) (image.Registry, cleanupFunc) { val, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64)) require.NoError(t, err) r, err := containerdregistry.NewRegistry( containerdregistry.WithLog(logrus.New().WithField("test", t.Name())), containerdregistry.WithCacheDir(fmt.Sprintf("cache-%x", val)), - containerdregistry.WithRootCAs(poolForCertFile(t, cafile)), + containerdregistry.WithRootCAs(poolForCert(serverCert)), ) require.NoError(t, err) cleanup := func() { @@ -59,30 +89,6 @@ func TestRegistries(t *testing.T) { return r, cleanup }, - // TODO: enable docker tests - currently blocked on a cross-platform way to configure either insecure registries - // or CA certs - //"docker": func(t *testing.T, cafile string) (image.Registry, cleanupFunc) { - // r, err := execregistry.NewRegistry(containertools.DockerTool, - // logrus.New().WithField("test", t.Name()), - // cafile, - // ) - // require.NoError(t, err) - // cleanup := func() { - // require.NoError(t, r.Destroy()) - // } - // - // return r, cleanup - //}, - // TODO: Enable buildah tests - // func(t *testing.T) image.Registry { - // r, err := buildahregistry.NewRegistry( - // buildahregistry.WithLog(logrus.New().WithField("test", t.Name())), - // buildahregistry.WithCacheDir(fmt.Sprintf("cache-%x", rand.Int())), - // ) - // require.NoError(t, err) - - // return r - // }, } for name, registry := range registries { @@ -90,6 +96,18 @@ func TestRegistries(t *testing.T) { } } +type httpError struct { + statusCode int + error error +} + +func (e *httpError) Error() string { + if e.error != nil { + return e.error.Error() + } + return http.StatusText(e.statusCode) +} + func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) { type args struct { dockerRootDir string @@ -100,7 +118,18 @@ func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) { type expected struct { checksum string pullAssertion require.ErrorAssertionFunc + labels map[string]string } + + expectedLabels := map[string]string{ + "operators.operatorframework.io.bundle.mediatype.v1": "registry+v1", + "operators.operatorframework.io.bundle.manifests.v1": "manifests/", + "operators.operatorframework.io.bundle.metadata.v1": "metadata/", + "operators.operatorframework.io.bundle.package.v1": "kiali", + "operators.operatorframework.io.bundle.channels.v1": "stable,alpha", + "operators.operatorframework.io.bundle.channel.default.v1": "stable", + } + tests := []struct { description string args args @@ -114,6 +143,7 @@ func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) { }, expected: expected{ checksum: dirChecksum(t, "testdata/golden/bundles/kiali"), + labels: expectedLabels, pullAssertion: require.NoError, }, }, @@ -125,6 +155,7 @@ func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) { }, expected: expected{ checksum: dirChecksum(t, "testdata/golden/bundles/kiali"), + labels: expectedLabels, pullAssertion: require.NoError, }, }, @@ -134,10 +165,11 @@ func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) { dockerRootDir: "testdata/golden", img: "/olmtest/kiali:1.4.2", pullErrCount: 1, - pullErr: errors.New("dummy"), + pullErr: &httpError{statusCode: http.StatusTooManyRequests}, }, expected: expected{ checksum: dirChecksum(t, "testdata/golden/bundles/kiali"), + labels: expectedLabels, pullAssertion: require.NoError, }, }, @@ -158,7 +190,7 @@ func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) { dockerRootDir: "testdata/golden", img: "/olmtest/kiali:1.4.2", pullErrCount: math.MaxInt64, - pullErr: errors.New("dummy"), + pullErr: &httpError{statusCode: http.StatusTooManyRequests}, }, expected: expected{ pullAssertion: require.Error, @@ -168,51 +200,43 @@ func testPullAndUnpack(t *testing.T, name string, newRegistry newRegistryFunc) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { logrus.SetLevel(logrus.DebugLevel) - ctx, close := context.WithCancel(context.Background()) - defer close() - - configOpts := []libimage.ConfigOpt{} + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var middlewares []func(next http.Handler) http.Handler if tt.args.pullErrCount > 0 { - configOpts = append(configOpts, func(config *configuration.Configuration) { - if config.Middleware == nil { - config.Middleware = make(map[string][]configuration.Middleware) - } - - mockRepo := &mockRepo{blobStore: &mockBlobStore{ - maxCount: tt.args.pullErrCount, - err: tt.args.pullErr, - }} - val, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64)) - require.NoError(t, err) - - middlewareName := fmt.Sprintf("test-%x", val) - require.NoError(t, repositorymiddleware.Register(middlewareName, mockRepo.init)) - config.Middleware["repository"] = append(config.Middleware["repository"], configuration.Middleware{ - Name: middlewareName, - }) - }) + middlewares = append(middlewares, failureMiddleware(tt.args.pullErrCount, tt.args.pullErr)) } - host, cafile, err := libimage.RunDockerRegistry(ctx, tt.args.dockerRootDir, configOpts...) - require.NoError(t, err) + dockerServer := libimage.RunDockerRegistry(ctx, tt.args.dockerRootDir, middlewares...) + defer dockerServer.Close() - r, cleanup := newRegistry(t, cafile) + r, cleanup := newRegistry(t, dockerServer.Certificate()) defer cleanup() - ref := image.SimpleReference(host + tt.args.img) - tt.expected.pullAssertion(t, r.Pull(ctx, ref)) + url, err := url.Parse(dockerServer.URL) + require.NoError(t, err) - if tt.expected.checksum != "" { - // Copy golden manifests to a temp dir - dir := "kiali-unpacked" - require.NoError(t, r.Unpack(ctx, ref, dir)) + ref := image.SimpleReference(fmt.Sprintf("%s%s", url.Host, tt.args.img)) + t.Log("pulling image", ref) + pullErr := r.Pull(ctx, ref) + tt.expected.pullAssertion(t, pullErr) + if pullErr != nil { + return + } - checksum := dirChecksum(t, dir) - require.Equal(t, tt.expected.checksum, checksum) + labels, err := r.Labels(ctx, ref) + require.NoError(t, err) + require.Equal(t, tt.expected.labels, labels) - require.NoError(t, os.RemoveAll(dir)) - } + // Copy golden manifests to a temp dir + dir := "kiali-unpacked" + require.NoError(t, r.Unpack(ctx, ref, dir)) + + checksum := dirChecksum(t, dir) + require.Equal(t, tt.expected.checksum, checksum) + + require.NoError(t, os.RemoveAll(dir)) }) } } @@ -303,3 +327,24 @@ func (f *mockBlobStore) ServeBlob(ctx context.Context, w http.ResponseWriter, r func (f *mockBlobStore) Delete(ctx context.Context, dgst digest.Digest) error { return f.base.Delete(ctx, dgst) } + +func failureMiddleware(totalCount int, err error) func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + count := 0 + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if count >= totalCount { + next.ServeHTTP(w, r) + return + } + count++ + statusCode := http.StatusInternalServerError + + var httpErr *httpError + if errors.As(err, &httpErr) { + statusCode = httpErr.statusCode + } + + http.Error(w, err.Error(), statusCode) + }) + } +} diff --git a/pkg/lib/image/registry.go b/pkg/lib/image/registry.go deleted file mode 100644 index c535379ae..000000000 --- a/pkg/lib/image/registry.go +++ /dev/null @@ -1,218 +0,0 @@ -package image - -import ( - "bytes" - "context" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/tls" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "fmt" - "io" - "math/big" - "net" - "net/http" - "os" - "time" - - "github.com/distribution/distribution/v3/configuration" - "github.com/distribution/distribution/v3/registry" - _ "github.com/distribution/distribution/v3/registry/storage/driver/filesystem" // Driver for persisting docker image data to the filesystem. - _ "github.com/distribution/distribution/v3/registry/storage/driver/inmemory" // Driver for keeping docker image data in memory. - "github.com/phayes/freeport" - "k8s.io/apimachinery/pkg/util/wait" -) - -type ConfigOpt func(*configuration.Configuration) - -// RunDockerRegistry runs a docker registry on an available port and returns its host string if successful, otherwise it returns an error. -// If the rootDir argument isn't empty, the registry is configured to use this as the root directory for persisting image data to the filesystem. -// If the rootDir argument is empty, the registry is configured to keep image data in memory. -func RunDockerRegistry(ctx context.Context, rootDir string, configOpts ...ConfigOpt) (string, string, error) { - dockerPort, err := freeport.GetFreePort() - if err != nil { - return "", "", err - } - host := fmt.Sprintf("localhost:%d", dockerPort) - certPool := x509.NewCertPool() - - cafile, err := os.CreateTemp("", "ca") - if err != nil { - return "", "", err - } - certfile, err := os.CreateTemp("", "cert") - if err != nil { - return "", "", err - } - keyfile, err := os.CreateTemp("", "key") - if err != nil { - return "", "", err - } - if err := GenerateCerts(cafile, certfile, keyfile, certPool); err != nil { - return "", "", err - } - if err := cafile.Close(); err != nil { - return "", "", err - } - if err := certfile.Close(); err != nil { - return "", "", err - } - if err := keyfile.Close(); err != nil { - return "", "", err - } - - config := &configuration.Configuration{} - config.HTTP.Addr = host - config.HTTP.TLS.Certificate = certfile.Name() - config.HTTP.TLS.Key = keyfile.Name() - config.Log.Level = "error" - - if rootDir != "" { - config.Storage = map[string]configuration.Parameters{"filesystem": map[string]interface{}{ - "rootdirectory": rootDir, - }} - } else { - config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}} - } - config.HTTP.DrainTimeout = 2 * time.Second - - for _, opt := range configOpts { - opt(config) - } - - dockerRegistry, err := registry.NewRegistry(ctx, config) - if err != nil { - return "", "", err - } - - go func() { - defer func() { - os.Remove(cafile.Name()) - os.Remove(certfile.Name()) - os.Remove(keyfile.Name()) - }() - if err := dockerRegistry.ListenAndServe(); err != nil { - panic(fmt.Errorf("docker registry stopped listening: %v", err)) - } - }() - - // nolint:staticcheck - err = wait.Poll(100*time.Millisecond, 10*time.Second, func() (bool, error) { - tr := &http.Transport{TLSClientConfig: &tls.Config{ - InsecureSkipVerify: false, - RootCAs: certPool, - MinVersion: tls.VersionTLS12, - }} - client := &http.Client{Transport: tr} - r, err := client.Get("https://" + host + "/v2/") - if err != nil { - return false, nil - } - defer r.Body.Close() - if r.StatusCode == http.StatusOK { - return true, nil - } - return false, nil - }) - if err != nil { - return "", "", err - } - - // Return the registry host string - return host, cafile.Name(), nil -} - -func certToPem(der []byte) ([]byte, error) { - out := &bytes.Buffer{} - if err := pem.Encode(out, &pem.Block{Type: "CERTIFICATE", Bytes: der}); err != nil { - return nil, err - } - return out.Bytes(), nil -} - -func keyToPem(key *ecdsa.PrivateKey) ([]byte, error) { - b, err := x509.MarshalECPrivateKey(key) - if err != nil { - return nil, fmt.Errorf("unable to marshal private key: %v", err) - } - out := &bytes.Buffer{} - if err := pem.Encode(out, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}); err != nil { - return nil, err - } - return out.Bytes(), nil -} - -func GenerateCerts(caWriter, certWriter, keyWriter io.Writer, pool *x509.CertPool) error { - priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) - if err != nil { - return err - } - ca := x509.Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{ - Organization: []string{"test ca"}, - }, - NotBefore: time.Now(), - NotAfter: time.Now().Add(time.Hour), - - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, - IsCA: true, - } - cert := x509.Certificate{ - SerialNumber: big.NewInt(2), - Subject: pkix.Name{ - Organization: []string{"test cert"}, - }, - NotBefore: time.Now(), - NotAfter: time.Now().Add(time.Hour), - - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, - IPAddresses: []net.IP{ - net.ParseIP("127.0.0.1"), - net.ParseIP("::1"), - }, - DNSNames: []string{"localhost"}, - } - - caBytes, err := x509.CreateCertificate(rand.Reader, &ca, &ca, &priv.PublicKey, priv) - if err != nil { - return err - } - - caFile, err := certToPem(caBytes) - if err != nil { - return err - } - if _, err := caWriter.Write(caFile); err != nil { - return err - } - pool.AppendCertsFromPEM(caFile) - - certBytes, err := x509.CreateCertificate(rand.Reader, &cert, &ca, &priv.PublicKey, priv) - if err != nil { - return err - } - certFile, err := certToPem(certBytes) - if err != nil { - return err - } - if _, err := certWriter.Write(certFile); err != nil { - return err - } - - keyFile, err := keyToPem(priv) - if err != nil { - return err - } - if _, err := keyWriter.Write(keyFile); err != nil { - return err - } - return nil -} diff --git a/release/goreleaser.darwin.yaml b/release/goreleaser.darwin.yaml index b60071040..d0d47ff79 100644 --- a/release/goreleaser.darwin.yaml +++ b/release/goreleaser.darwin.yaml @@ -10,7 +10,7 @@ builds: - CGO_ENABLED=1 mod_timestamp: "{{ .CommitTimestamp }}" flags: &build-flags - - -tags=json1 + - -tags=json1,containers_image_openpgp asmflags: &build-asmflags - all=-trimpath={{ .Env.PWD }} gcflags: &build-gcflags diff --git a/release/goreleaser.linux.yaml b/release/goreleaser.linux.yaml index 2f69f8dd5..2822d1d30 100644 --- a/release/goreleaser.linux.yaml +++ b/release/goreleaser.linux.yaml @@ -11,7 +11,7 @@ builds: - CGO_ENABLED=1 mod_timestamp: "{{ .CommitTimestamp }}" flags: &build-flags - - -tags=json1,netgo,osusergo + - -tags=json1,netgo,osusergo,containers_image_openpgp asmflags: &build-asmflags - all=-trimpath={{ .Env.PWD }} gcflags: &build-gcflags diff --git a/release/goreleaser.windows.yaml b/release/goreleaser.windows.yaml index 4232f5eea..b35be4c7a 100644 --- a/release/goreleaser.windows.yaml +++ b/release/goreleaser.windows.yaml @@ -10,7 +10,7 @@ builds: - CGO_ENABLED=1 mod_timestamp: "{{ .CommitTimestamp }}" flags: &build-flags - - -tags=json1,netgo,osusergo + - -tags=json1,netgo,osusergo,containers_image_openpgp asmflags: &build-asmflags - all=-trimpath={{ .Env.PWD }} gcflags: &build-gcflags diff --git a/test/e2e/opm_bundle_test.go b/test/e2e/opm_bundle_test.go index b1161fea6..f761261e8 100644 --- a/test/e2e/opm_bundle_test.go +++ b/test/e2e/opm_bundle_test.go @@ -3,7 +3,10 @@ package e2e_test import ( "bytes" "context" + "encoding/pem" "io" + "net/http/httptest" + "net/url" "os" "path/filepath" @@ -12,7 +15,7 @@ import ( "golang.org/x/mod/sumdb/dirhash" - libimage "github.com/operator-framework/operator-registry/pkg/lib/image" + libimage "github.com/operator-framework/operator-registry/internal/testutil/image" ) var _ = Describe("opm alpha bundle", func() { @@ -32,29 +35,34 @@ var _ = Describe("opm alpha bundle", func() { bundleChecksum string tmpDir string rootCA string - stopRegistry func() + server *httptest.Server ) BeforeEach(func() { ctx, cancel := context.WithCancel(context.Background()) - stopRegistry = func() { - cancel() - <-ctx.Done() - } + defer cancel() // Spin up an in-process docker registry with a set of preconfigured test images var ( // Directory containing the docker registry filesystem goldenFiles = "../../pkg/image/testdata/golden" - - host string - err error ) - host, rootCA, err = libimage.RunDockerRegistry(ctx, goldenFiles) - Expect(err).ToNot(HaveOccurred()) + server := libimage.RunDockerRegistry(ctx, goldenFiles) + serverURL, err := url.Parse(server.URL) + Expect(err).NotTo(HaveOccurred()) + + caFile, err := os.CreateTemp("", "ca") + Expect(err).NotTo(HaveOccurred()) + + Expect(pem.Encode(caFile, &pem.Block{ + Type: "CERTIFICATE", + Bytes: server.Certificate().Raw, + })).To(Succeed()) + rootCA = caFile.Name() + caFile.Close() // Create a bundle ref using the local registry host name and the namespace/name of a bundle we already know the content of - bundleRef = host + "/" + imageDomain + "/kiali@sha256:a1bec450c104ceddbb25b252275eb59f1f1e6ca68e0ced76462042f72f7057d8" + bundleRef = serverURL.Host + imageDomain + "/kiali@sha256:a1bec450c104ceddbb25b252275eb59f1f1e6ca68e0ced76462042f72f7057d8" // Generate a checksum of the expected content for the bundle under test bundleChecksum, err = dirhash.HashDir(filepath.Join(goldenFiles, "bundles/kiali"), "", dirhash.DefaultHash) @@ -66,12 +74,13 @@ var _ = Describe("opm alpha bundle", func() { }) AfterEach(func() { - stopRegistry() + server.Close() if CurrentGinkgoTestDescription().Failed { // Skip additional cleanup return } + Expect(os.RemoveAll(rootCA)).To(Succeed()) Expect(os.RemoveAll(tmpDir)).To(Succeed()) })