docker_auth
docker_auth copied to clipboard
Is there a possibility of allowing public images to be pulled without credentials in a private docker registry deployment using docker auth?
We have used this docker-auth implementation to handle authentication and authorization mechanisms in one of our projects using a private docker registry. In there we have a concept of private and public images belonging to different organizations. In our implementation, there is a use case where we should allow the users to pull public images in an organization in the docker registry without logging in to the registry.
In the docker auth implementation it could be seen that in every request received at docker auth end-point, it tries to validate the credentials using authentication logic. In a scenario of pulling public images without logging in, this fails since for authentication we don't have valid credentials.
So I want to know whether there is a way to handle this scenario? Thank you!
this is very much a supported use case but i think i broke it in a recent commit (https://github.com/cesanta/docker_auth/commit/9c17b9ae2427bc48259a5825fcf4b25740e5ba17 PR https://github.com/cesanta/docker_auth/pull/251). i have now reverted the commit (https://github.com/cesanta/docker_auth/commit/f1a115f5e2a7f6ce2d4fc07b833bf2c704fdf3e8).
to allow anonymous access you need an authentication module that accepts empty usernames. the easiest is the static user list with an entry as shown here:
users:
"": {} # Allow anonymous (no "docker login") access.
then, you need to allow no-account users to access to repositores, example here.
i pushed new cesanta/docker_auth:latest (version 2019082622), please try now.
Hi @rojer
This looks like a static approach where you allow antonymous pulls to specific repositories (In your sample it's hello-world). Ours is more dynamic. There can be large number of images (repositories) and their privacy status (private/public) can be changed dynamically. Hence we need a way to control access on demand by looking up a DB. Since the above mentioned approach is a static approach it looks like we can't use it. Please correct me if I am wrong.
If I explain what we want in brief, to be more clear, the authorization logic should decide whether to allow or deny an action by taking the authentication result into consideration. Authentication logic should not send back a result without executing authorization logic.
Or else if we can get more information/data like repositories and action into authentication extension, we can execute the authorization logic at authentication extension itself as a workaround.
authentication stage has access to username and password, authorization stage has access to username and repository information. both have options to perform authentication dynamically, like storing and updating ACLs in mongodb, invoking an external command or (just added) an external function from a plugin (shared library). see collection of example configs here.
Hi @rojer
It looks like there's a gap between our understandings. Would it be possible to have a discussion on this ? May be a call ?
docker_auth is a hobby project for me, i don't provide phone support.
let me try to clarify.
if your set of users is static, you can use static authentication stage. authentication should also allow public access requests (no username) to proceed.
it looks like your authrization stage is highly dynamic, and here you may be able to use mongodb and manage ACLs dynamically, or just invoke and external program that will apply whatever rules you need to make the decision. if the performance of spawning a process per request (CGI-style) is a problem, impkement your logic in a shared object file and use the plugin_authz (added recently in https://github.com/cesanta/docker_auth/pull/254).
As you suggest we are already using an external program using a plugin. What happened there is it always calls authentication logic, so that unauthorized users can not pull public images. If we can get the authorized scopes to authentication, we can pull public images. That is basically our requirement. Shall I put a PR implementing this feature to the plugin?
always calls authentication logic, so that unauthorized users can not pull public images
this is not correct. authentication is always invoked, yes, but it can allow unidentified users if necessary. i described above how to do it.
Hi @rojer
Using a mongo db to store dynamic ACL is an overhead as per our current implementation. Instead, if we can get repositories and actions to the authentication plugin, we can sort this out the issue in an easier way. If you think this is something docker auth can cater I can send a PR to cater this change to the new authz plugin extension which I implemented previously.
docker_auth architecture makes clear separation between authentication an authorization phases:
- authentication plugins are only concerned with establishing whether the user is who they claim to be, i.e. checking the password.
- authorization plugins decide, what the user is allowed to do - which repos to pull or push. at that point account they are acting under has already been verified, so it can be taken as a given.
if your use case involves public access in some form, just have your authn phase allow access to users with empty username: if username/password are provided - validate, reject if the combination is wrong; if username is not provided - allow and let authz deal with it.
then, when your authz plugin is called, public access requests will have account empty. deal with them however you see fit. if account is set, it means it is an authenticated request and the password has already been validated.
Ok... Let’s assume we can handle user account at the authorization by seeing the account emptiness. We have done our project using your ext-auth. But when there is a docker-auth ping request at docker auth endpoint, the request does not get passed to the authorization logic. Since we are passing through authentication logic without failing irrespective of the auth status the ping will always be successful. How can we handle this scenario?
i don't know anything about ping request. when are they used, how do they look like (uri, headers) and why don't then go to authz logic?
By ping, @tharindulak is talking about the api version check API endpoint in the Docker registry. AFAIK, this request does not contain any scopes or actions since it is a simple API version check.
From a quick look at the code base, when the list of scopes is empty the authorize logic is not called. Hence we are probably observing this behavior.
I have tried the /v2/ endpoint on Docker Hub (https://registry-1.docker.io/v2/) and it seems to be sending a 401 response when the credentials are not present. So I assume that the expected behavior of this endpoint is to validate the credentials properly and authenticate.
This is generally used for validating credentials in docker login. Therefore, the suggested approach would potential break the docker login behavior (The login would always be successful even if the credentials are invalid).
I am wondering whether there is a way to achieve a similar behavior, while also catering to the requirement of achieving the above mentioned requirements by @tharindulak and @hasinthaindrajee .
ok, i see the problem. any suggestions on how to solve it?
If we can bring the auth request scopes to authentication logic we can solve this problem. I can implement it to the plugin auth implementation. Therefore it will not break the other flows.
no, if we are making an API change, it needs to be made uniformly to all implementations.
i'm not sure what the change should be though. can you research it and find some documentation about authentication for the /v2/ and maybe other endpoints?
We have two options that can solve this problem according to me.
- To change apis of all authenticators and add scopes to each of them.
- Execute authorization to ping request. Both of them in a backward compatible way(may be a config change).
Hi @rojer What are your thoughts on the above solutions?
I use external auth method and I've noticed that for anon user it doesn't even execs the command, is this by design?
I tried combining static anon user with ext_auth and it does work for anon but breaks my external auth.