diff --git a/binderhub/registry.py b/binderhub/registry.py index f7788bea1..94ebdd92e 100644 --- a/binderhub/registry.py +++ b/binderhub/registry.py @@ -339,6 +339,35 @@ async def get_credentials(self, image, tag): return None +class GoogleArtifactRegistry(DockerRegistry): + """ + A registry for Google Artifact Registry. + + At present, the only way to generate credentials without having to use the gcloud cli + is the metadata server. The metadata server uses the Compute Engine default service account. + + For more information, see https://cloud.google.com/docs/authentication/rest#metadata-server. + """ + + @default("token_url") + def _default_token_url(self): + return "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" + + async def _get_token(self, client, token_url, service, scope): + auth_req = httpclient.HTTPRequest( + token_url, headers={"Metadata-Flavor": "Google"} + ) + self.log.debug(f"Getting registry token from {token_url}") + auth_resp = await client.fetch(auth_req) + response_body = json.loads(auth_resp.body.decode("utf-8", "replace")) + + if "access_token" in response_body.keys(): + token = response_body["access_token"] + else: + raise ValueError(f"No token in response from registry: {response_body}") + return token + + class FakeRegistry(DockerRegistry): """ Fake registry that contains no images