From fd7e09820590b26c0eb6110b2044aafc3a9d22ce Mon Sep 17 00:00:00 2001 From: Lubos Mjachky Date: Fri, 7 Jan 2022 19:12:13 +0100 Subject: [PATCH] Add an extensions API endpoint for downloading signatures closes #504 --- CHANGES/504.feature | 1 + pulp_container/app/registry_api.py | 46 ++++++++++++++++++- pulp_container/app/urls.py | 2 + .../app/webserver_snippets/apache.conf | 3 ++ .../app/webserver_snippets/nginx.conf | 10 ++++ 5 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 CHANGES/504.feature diff --git a/CHANGES/504.feature b/CHANGES/504.feature new file mode 100644 index 000000000..49efdca8e --- /dev/null +++ b/CHANGES/504.feature @@ -0,0 +1 @@ +Added an extensions API endpoint for downloading image signatures. diff --git a/pulp_container/app/registry_api.py b/pulp_container/app/registry_api.py index dca2a781a..879ff5c42 100644 --- a/pulp_container/app/registry_api.py +++ b/pulp_container/app/registry_api.py @@ -292,7 +292,12 @@ def default_response_headers(self): Provide common headers to all responses. """ headers = super().default_response_headers - headers.update({"Docker-Distribution-Api-Version": "registry/2.0"}) + headers.update( + { + "Docker-Distribution-Api-Version": "registry/2.0", + "X-Registry-Supports-Signatures": "1", + } + ) return headers def get_exception_handler_context(self): @@ -970,3 +975,42 @@ def receive_artifact(self, chunk): artifact = Artifact.objects.get(sha256=artifact.sha256) artifact.touch() return artifact + + +class Signatures(ContainerRegistryApiMixin, ViewSet): + """A ViewSet for image signatures.""" + + lookup_value_regex = "sha256:[0-9a-f]+" + + def head(self, request, path, pk=None): + """Respond to HEAD requests querying signatures by sha256.""" + return self.get(request, path, pk=pk) + + def get(self, request, path, pk): + """Return a signature identified by its sha256 checksum.""" + distribution, _, repository_version = self.get_drv_pull(path) + + try: + manifest = models.Manifest.objects.get(digest=pk) + except models.Manifest.DoesNotExit: + raise ManifestNotFound(reference=pk) + + signatures = models.ManifestSignature.objects.filter( + signed_manifest=manifest, pk__in=repository_version.content + ) + + return Response(self.get_response_data(signatures)) + + @staticmethod + def get_response_data(signatures): + """Extract version, type, name, and content from the passed signature data.""" + data = [] + for signature in signatures: + signature = { + "version": 2, + "type": signature.type, + "name": signature.name, + "content": signature.data.tobytes().decode(), + } + data.append(signature) + return {"signatures": data} diff --git a/pulp_container/app/urls.py b/pulp_container/app/urls.py index b600b3026..0b7786561 100644 --- a/pulp_container/app/urls.py +++ b/pulp_container/app/urls.py @@ -6,6 +6,7 @@ BlobUploads, CatalogView, Manifests, + Signatures, TagsListView, VersionView, ) @@ -25,6 +26,7 @@ router.register(r"^v2/(?P.+)/blobs/uploads\/?", BlobUploads, basename="docker-upload") router.register(r"^v2/(?P.+)/blobs", Blobs, basename="blobs") router.register(r"^v2/(?P.+)/manifests", Manifests, basename="manifests") +router.register(r"^extensions/v2/(?P.+)/signatures", Signatures, basename="signatures") urlpatterns = [ path("token/", BearerTokenView.as_view()), diff --git a/pulp_container/app/webserver_snippets/apache.conf b/pulp_container/app/webserver_snippets/apache.conf index f52664a00..e7e2f6989 100644 --- a/pulp_container/app/webserver_snippets/apache.conf +++ b/pulp_container/app/webserver_snippets/apache.conf @@ -1,6 +1,9 @@ ProxyPass /v2 ${pulp-api}/v2 ProxyPassReverse /v2 ${pulp-api}/v2 +ProxyPass /extensions/v2 ${pulp-api}/extensions/v2 +ProxyPassReverse /extensions/v2 ${pulp-api}/extensions/v2 + ProxyPass /pulp/container ${pulp-content}/pulp/container ProxyPassReverse /pulp/container ${pulp-content}/pulp/container diff --git a/pulp_container/app/webserver_snippets/nginx.conf b/pulp_container/app/webserver_snippets/nginx.conf index 765cc0837..1034fe3d8 100644 --- a/pulp_container/app/webserver_snippets/nginx.conf +++ b/pulp_container/app/webserver_snippets/nginx.conf @@ -9,6 +9,16 @@ location /v2/ { client_max_body_size 0; } +location extensions/v2/ { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + # we don't want nginx trying to do something clever with + # redirects, we set the Host: header above already. + proxy_redirect off; + proxy_pass http://pulp-api; +} + location /pulp/container/ { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;