[go: up one dir, main page]

Skip to content

fix(handlers): handle the /gitlab/v1 API with the database disabled

Context

The new /gitlab/v1 API is only available when the metadata database is enabled. These endpoints will query the database before attempting to check any backend storage to ensure the metadata database knows about the container repositories.

Problem

Although the metadata database is only used on GitLab.com and is not recommended to be used in self-managed installations yet, we should handle cases where a user attempts to use any of the /gitlab/v1/ endpoints without the database configured properly.

Currently, if the registry is run without the database configured correctly, and an endpoint such as /gitlab/v1/repositories/<name> is accessed, the server will panic and the response is not sent back correctly to the client.

export REGISTRY_DATABASE_ENABLED=false
❯ make bin/registry && ./bin/registry serve myenv/config.yml
+ bin/registry
WARN[0000] No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable.  go_version=go1.19.1 instance_id=93867cad-65c5-4270-b798-7fe0c3b5d3a2 service=registry version=v3.57.0-gitlab-36-g47b38aaf.m
INFO[0000] configuring endpoint pipedream (http://registry.test:3333/), timeout=500ms, headers=map[Authorization:[gitlab-registry-notification]]  go_version=go1.19.1 instance_id=93867cad-65c5-4270-b798-7fe0c3b5d3a2 service=registry version=v3.57.0-gitlab-36-g47b38aaf.m
INFO[0000] Starting upload purge in 40m0s                go_version=go1.19.1 instance_id=93867cad-65c5-4270-b798-7fe0c3b5d3a2 service=registry version=v3.57.0-gitlab-36-g47b38aaf.m
ERRO[0000] failed configuring Redis cache                error="dial tcp [::1]:6379: connect: connection refused" go_version=go1.19.1 instance_id=93867cad-65c5-4270-b798-7fe0c3b5d3a2 service=registry version=v3.57.0-gitlab-36-g47b38aaf.m
INFO[0000] storage backend redirection enabled           go_version=go1.19.1 instance_id=93867cad-65c5-4270-b798-7fe0c3b5d3a2 service=registry version=v3.57.0-gitlab-36-g47b38aaf.m
INFO[0000] listening on [::]:5000                        go_version=go1.19.1 instance_id=93867cad-65c5-4270-b798-7fe0c3b5d3a2 service=registry version=v3.57.0-gitlab-36-g47b38aaf.m
INFO[0000] starting health checker                       address=":5001" go_version=go1.19.1 instance_id=93867cad-65c5-4270-b798-7fe0c3b5d3a2 path=/debug/health version=v3.57.0-gitlab-36-g47b38aaf.m
INFO[0000] starting Prometheus listener                  address=":5001" go_version=go1.19.1 instance_id=93867cad-65c5-4270-b798-7fe0c3b5d3a2 path=/metrics version=v3.57.0-gitlab-36-g47b38aaf.m
INFO[0000] starting pprof listener                       address=":5001" go_version=go1.19.1 instance_id=93867cad-65c5-4270-b798-7fe0c3b5d3a2 path=/debug/pprof/ version=v3.57.0-gitlab-36-g47b38aaf.m
DEBU[0001] authorizing request                           correlation_id=01GF09TP7GB9TD2JX3FXQBN19T go_version=go1.19.1 version=v3.57.0-gitlab-36-g47b38aaf.m
PANI[0001] runtime error: invalid memory address or nil pointer dereference
{"content_type":"","correlation_id":"01GF09TP7GB9TD2JX3FXQBN19T","duration_ms":0,"host":"registry.test:5000","level":"info","method":"GET","msg":"access","proto":"HTTP/1.1","referrer":"","remote_addr":"172.16.123.1:61137","remote_ip":"172.16.123.1","status":0,"system":"http","time":"2022-10-10T17:38:00.945+11:00","uri":"/gitlab/v1/repositories/root/registry-test/alpine/tags/list/","user_agent":"curl/7.79.1","written_bytes":0}
2022/10/10 17:38:00 http: panic serving 172.16.123.1:61137: &{0x14000200000 map[] 2022-10-10 17:38:00.945204 +1100 AEDT m=+1.469409834 panic <nil> runtime error: invalid memory address or nil pointer dereference <nil> <nil> }
goroutine 32 [running]:
net/http.(*conn).serve.func1()
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:1850 +0xb0
panic({0x1017b96a0, 0x140002ba380})
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/runtime/panic.go:890 +0x258
github.com/sirupsen/logrus.(*Entry).log(0x140002ba000, 0x0, {0x14000612080, 0x40})
	/Users/jaime/.asdf/installs/golang/1.19.1/packages/pkg/mod/github.com/sirupsen/logrus@v1.9.0/entry.go:260 +0x49c
github.com/sirupsen/logrus.(*Entry).Log(0x140002ba000, 0x0, {0x1400060a7b8?, 0x1015ef5e0?, 0x14000612001?})
	/Users/jaime/.asdf/installs/golang/1.19.1/packages/pkg/mod/github.com/sirupsen/logrus@v1.9.0/entry.go:304 +0x60
github.com/sirupsen/logrus.(*Logger).Log(0x14000200000, 0x0, {0x1400060a7b8, 0x1, 0x1})
	/Users/jaime/.asdf/installs/golang/1.19.1/packages/pkg/mod/github.com/sirupsen/logrus@v1.9.0/logger.go:204 +0x60
github.com/sirupsen/logrus.(*Logger).Panic(...)
	/Users/jaime/.asdf/installs/golang/1.19.1/packages/pkg/mod/github.com/sirupsen/logrus@v1.9.0/logger.go:253
github.com/sirupsen/logrus.Panic(...)
	/Users/jaime/.asdf/installs/golang/1.19.1/packages/pkg/mod/github.com/sirupsen/logrus@v1.9.0/exported.go:129
github.com/docker/distribution/registry.panicHandler.func1.1()
	/Users/jaime/dev/gitlab/container-registry/registry/registry.go:492 +0x88
panic({0x101663bc0, 0x10205c320})
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/runtime/panic.go:884 +0x204
github.com/docker/distribution/registry/datastore.(*DB).QueryRowContext(0x140000ae080?, {0x1017f23e8?, 0x14000462120?}, {0x101261541?, 0x1025e0a68?}, {0x140004f6140?, 0x140005a0000?, 0x1400043c080?})
	<autogenerated>:1 +0x10
github.com/docker/distribution/registry/datastore.(*repositoryStore).FindByPath(0x1400043c080, {0x1017f23e8, 0x14000462120}, {0x140000ae080, 0x19})
	/Users/jaime/dev/gitlab/container-registry/registry/datastore/repository.go:328 +0xf4
github.com/docker/distribution/registry/handlers.(*repositoryTagsHandler).GetTags(0x140000b2010, {0x129d50e30, 0x140004f45d0}, 0x14000318600)
	/Users/jaime/dev/gitlab/container-registry/registry/handlers/repositories.go:247 +0x70c
net/http.HandlerFunc.ServeHTTP(0x101694660?, {0x129d50e30?, 0x140004f45d0?}, 0x3?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
github.com/gorilla/handlers.MethodHandler.ServeHTTP(0x14000462120?, {0x129d50e30, 0x140004f45d0}, 0x14000318600)
	/Users/jaime/.asdf/installs/golang/1.19.1/packages/pkg/mod/github.com/gorilla/handlers@v1.5.1/handlers.go:30 +0xb0
github.com/docker/distribution/registry/handlers.(*App).dispatcherGitlab.func1({0x129d50e30, 0x140004f45d0}, 0x14000318500)
	/Users/jaime/dev/gitlab/container-registry/registry/handlers/app.go:1305 +0x3bc
net/http.HandlerFunc.ServeHTTP(0x129d50e30?, {0x129d50e30?, 0x140004f45d0?}, 0x100e201dc?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
github.com/docker/distribution/registry/handlers/internal/metrics/promhttp.InstrumentHandlerCounter.func1({0x129d50e30, 0x140004f45a0}, 0x14000318500)
	/Users/jaime/dev/gitlab/container-registry/registry/handlers/internal/metrics/promhttp/instrument_server.go:115 +0x90
net/http.HandlerFunc.ServeHTTP(0x129d50e30?, {0x129d50e30?, 0x140004f45a0?}, 0x4?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
github.com/docker/distribution/registry/handlers/internal/metrics/promhttp.InstrumentHandlerDuration.func1({0x129d50e30, 0x140004f4570}, 0x14000318500)
	/Users/jaime/dev/gitlab/container-registry/registry/handlers/internal/metrics/promhttp/instrument_server.go:80 +0xb8
net/http.HandlerFunc.ServeHTTP(0x0?, {0x129d50e30?, 0x140004f4570?}, 0x100e201dc?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
github.com/docker/distribution/registry/handlers/internal/metrics/promhttp.InstrumentHandlerInFlight.func1({0x129d50e30, 0x140004f4570}, 0x140004f4500?)
	/Users/jaime/dev/gitlab/container-registry/registry/handlers/internal/metrics/promhttp/instrument_server.go:52 +0xb0
net/http.HandlerFunc.ServeHTTP(0x129d50e30?, {0x129d50e30?, 0x140004f4570?}, 0x129d50ec0?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
github.com/docker/distribution/registry/handlers/internal/metrics/promhttp.InstrumentHandlerRequestSize.func1({0x129d50e30, 0x140004f4540}, 0x14000318500)
	/Users/jaime/dev/gitlab/container-registry/registry/handlers/internal/metrics/promhttp/instrument_server.go:182 +0x9c
net/http.HandlerFunc.ServeHTTP(0x129d50e30?, {0x129d50e30?, 0x140004f4540?}, 0x100682adc?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
github.com/docker/distribution/registry/handlers/internal/metrics/promhttp.InstrumentHandlerResponseSize.func1({0x129d50e30, 0x140004f4510}, 0x14000318500)
	/Users/jaime/dev/gitlab/container-registry/registry/handlers/internal/metrics/promhttp/instrument_server.go:217 +0x9c
net/http.HandlerFunc.ServeHTTP(0x1017eed10?, {0x129d50e30?, 0x140004f4510?}, 0x10098b890?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
github.com/docker/distribution/registry/handlers/internal/metrics/promhttp.InstrumentHandlerTimeToWriteHeader.func1({0x1017eed10?, 0x140000b0240}, 0x14000318500)
	/Users/jaime/dev/gitlab/container-registry/registry/handlers/internal/metrics/promhttp/instrument_server.go:156 +0x1ac
net/http.HandlerFunc.ServeHTTP(0x14000318400?, {0x1017eed10?, 0x140000b0240?}, 0x14000500080?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
github.com/gorilla/mux.(*Router).ServeHTTP(0x14000210240, {0x1017eed10, 0x140000b0240}, 0x14000318300)
	/Users/jaime/.asdf/installs/golang/1.19.1/packages/pkg/mod/github.com/gorilla/mux@v1.8.0/mux.go:210 +0x19c
github.com/docker/distribution/registry/handlers.(*App).ServeHTTP(0x14000205180, {0x129d50d60, 0x140004520c0}, 0x14000318100)
	/Users/jaime/dev/gitlab/container-registry/registry/handlers/app.go:1069 +0x2f0
github.com/docker/distribution/registry.panicHandler.func1({0x129d50d60?, 0x140004520c0?}, 0x140005307b8?)
	/Users/jaime/dev/gitlab/container-registry/registry/registry.go:495 +0x5c
net/http.HandlerFunc.ServeHTTP(0x101598731?, {0x129d50d60?, 0x140004520c0?}, 0x0?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
github.com/docker/distribution/registry.alive.func1({0x129d50d60?, 0x140004520c0?}, 0x0?)
	/Users/jaime/dev/gitlab/container-registry/registry/registry.go:512 +0x98
net/http.HandlerFunc.ServeHTTP(0x140001cc3a0?, {0x129d50d60?, 0x140004520c0?}, 0x100682adc?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
github.com/docker/distribution/health.Handler.func1({0x129d50d60, 0x140004520c0}, 0x0?)
	/Users/jaime/dev/gitlab/container-registry/health/health.go:271 +0x104
net/http.HandlerFunc.ServeHTTP(0x1017f12c0?, {0x129d50d60?, 0x140004520c0?}, 0x100?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
gitlab.com/gitlab-org/labkit/log.AccessLogger.func1({0x1017f12c0?, 0x14000476000?}, 0x14000318100)
	/Users/jaime/.asdf/installs/golang/1.19.1/packages/pkg/mod/gitlab.com/gitlab-org/labkit@v1.16.0/log/access_logger.go:23 +0xc0
net/http.HandlerFunc.ServeHTTP(0x1017f1f50?, {0x1017f12c0?, 0x14000476000?}, 0x1015396e0?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
gitlab.com/gitlab-org/labkit/correlation.InjectCorrelationID.func1({0x1017f12c0, 0x14000476000}, 0x14000318000)
	/Users/jaime/.asdf/installs/golang/1.19.1/packages/pkg/mod/gitlab.com/gitlab-org/labkit@v1.16.0/correlation/inbound_http.go:39 +0x304
net/http.HandlerFunc.ServeHTTP(0x0?, {0x1017f12c0?, 0x14000476000?}, 0x1008fabf8?)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2109 +0x38
net/http.serverHandler.ServeHTTP({0x140004f41e0?}, {0x1017f12c0, 0x14000476000}, 0x14000318000)
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:2947 +0x2c4
net/http.(*conn).serve(0x14000514be0, {0x1017f1ff8, 0x140004f40f0})
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:1991 +0x560
created by net/http.(*Server).Serve
	/Users/jaime/.asdf/installs/golang/1.19.1/go/src/net/http/server.go:3102 +0x444

Implementation Plan / Solution

We should add a check to the App handler dispatcher to see if the database is enabled. If it's not, we should simply return a 404. The check can be added inside the v1.RouteRegex match string if condition in https://gitlab.com/gitlab-org/container-registry/-/blob/1480f269f5ba51b9ab9ff8194ec93f460bbcae2e/registry/handlers/app.go#L1063

Edited by Michael Blum