oras-py icon indicating copy to clipboard operation
oras-py copied to clipboard

Support for `config.json` credHelpers

Open hanikesn opened this issue 1 year ago • 5 comments

A lot of legacy clients and for example the oras cli support credHelpers from ~/.docker/config.json. Support for those would be very helpful.

hanikesn avatar Jun 10 '24 19:06 hanikesn

This should already be supported here: https://github.com/oras-project/oras-py/blob/fd8a83ccb56f8779760648b09dee68c600b13d94/oras/provider.py#L188-L207 in that the DockerClient looks for that path. https://github.com/oras-project/oras-py/blob/fd8a83ccb56f8779760648b09dee68c600b13d94/oras/utils/request.py#L63

vsoch avatar Jun 10 '24 19:06 vsoch

I don't have a username or password, so client.login() will interactively ask for those. I'm using docker-credential-gcloud helper though, which doesn't need either.

I solved this by doing the following override in my registry:

    def load_configs(self, container: container_type, configs: Optional[list] = None):
        if self._basic_auth:
            return
        config = docker.auth.load_config()
        hostname = docker.auth.convert_to_hostname(self.hostname)
        auth = config.resolve_authconfig(hostname)
        self.set_basic_auth(username=auth['Username'], password=auth['Password'])

hanikesn avatar Jun 10 '24 21:06 hanikesn

We have a new set of auth backends for this purpose:

https://github.com/oras-project/oras-py/blob/main/oras/auth/base.py

What you'd do is subclass that base, and update the load_configs to be that (and edit the other functions if needed for google cloud). Would you be open to doing a PR with these changes? Then you could specify your auth backend and it should just work.

vsoch avatar Jun 10 '24 22:06 vsoch

I have the same usecase (access google cloud registry while the local docker client already has all the authentication set up). My guess is, using the new "base" auth code structure, the basic idea would look something like this (have not thought about error handling yet though):

import docker.auth
import oras.auth

class DockerClientAuth(oras.auth.BasicAuth):
    def _load_auth(self, hostname: str) -> bool:
        if super()._load_auth(hostname):
            return True
        config = docker.auth.load_config()
        hostname = docker.auth.convert_to_hostname(hostname)
        a = config.resolve_authconfig(hostname)
        self.set_basic_auth(username=a['Username'], password=a['Password'])
        return True

oras.auth.auth_backends['docker'] = DockerClientAuth

registry = Registry(auth_backend='docker')
filenames = registry.pull('europe-west3-docker.pkg.dev/myproject/myrepo:tag')

This of course depends on the https://pypi.org/project/docker/ package being installed.

wosc avatar Jun 20 '24 09:06 wosc

In case you missed the message above, we already have the docker client included and "login" is called from it:

https://github.com/oras-project/oras-py/blob/fd8a83ccb56f8779760648b09dee68c600b13d94/oras/utils/request.py#L63

I would be open to review a PR to address this need, from either of you.

vsoch avatar Jun 20 '24 12:06 vsoch