Have docker regsitry TLS to check client-certificates for user auth

Hello!

About the docker registry authentication, I’ve seen 2 methods up to now: Password (https://docs.docker.com/registry/deploying/#native-basic-auth) and Token (https://docs.docker.com/registry/spec/auth/token/).

According to this question in the security stackexchange https://security.stackexchange.com/questions/230893/how-can-i-double-check-security-against-a-tls-on-a-public-ip a server using TLS listening in a public IP which only will allow a set of previously-know users scattered over the world could be secured by handling client-certificates in the TLS layer.

Questions

a) Does the registry support client-certificates auth? Can I make https://hub.docker.com/_/registry to handle client-certificates on the TLS layer so I can kick-out any user trying to enter which is not in the white-listed keys? If so, where’s the documentation entry point?

b) If not, is it possible to offload the TLS part to OpenSSL and piping it to a non-TLS registry, so the OpenSSL handles both the secure channel and the authentication part?

If this is the way to go, I’ve already seen that here https://docs.docker.com/registry/recipes/ there are 2 recipes: One for apache and one for nginx, both acting as proxies.

But, IMHO, setting a fully-featured web-server just for handling a TLS certificate is a complete overkill.

I wonder of we can set a “simple proxy” saying like “Hey proxy, listen in this port, here there are your provate keys and certs, here there are the public keys of the client, and the non-crypted docker is here”, nothing else.

Reducing to a single question

In other words: What’s the simplest configuration that allows me to have the users auth’ed via public/private key pairs safe enough to be in a public IP as indicated in the security stackeexchange link above?

You can use nginx as a reverse proxy to perform mutual tls authentification:

   server {
        listen      443 ssl;
        server_name backend1.example.com;

        # idealy the fullchain.pem, including the server certificate and all intermediate certificates up to the root ca
        ssl_certificate        /etc/ssl/certs/server.crt;
        ssl_certificate_key    /etc/ssl/certs/server.key;
        # either the certificate of a ca where you trust all certificates it issued OR the concatentation of all client certificates accepted for client authentificationssl_client_certificate /etc/ssl/certs/ca.crt;
        ssl_verify_client      optional;

        location /yourapp {
            proxy_pass http://url_to_app.com;
        #...
        }
    # ...

Though, I have no idea wether the default certifcate files, used for mutual tls auth against a docker engine, will be used for interaction with a repo as well…

CA certificate: ~/docker/ca.pem
Client certificate: ~/.docker/cert.pem
Client key: ~/.docker/key.pem

Give it a try :slight_smile:

Isn’t a full web server like NGinX an overkill to just “crypt a channel”?

I posted a similar question just related to the offloading of the TLS channel (not related to docker registry, but general for any server) here https://security.stackexchange.com/q/230910/233270

gowenfawr suggests to use stunnel.

Is there any reason by which nginx would be preferrable over stunnel?

I mean… although nginx “can” do it, the question if that’s the “best” option from the security point of view, compared to a tool whose “only” purpose is security.

At the end it’s a matter of taste. As the registry already uses the http protocoll, putting a reverse proxy to offload tls and authentification feels natural to me. You can put both in the same docker-compose.yml and start the set of containers at once.

I am not going to argue wether to use nginx or stunnel. I always feel sticking to an industry wide accepted solution is the better choice.