Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a demo for the docker registry generic connector #1303

Closed
JakeQuilty opened this issue Jul 13, 2020 · 5 comments
Closed

Create a demo for the docker registry generic connector #1303

JakeQuilty opened this issue Jul 13, 2020 · 5 comments

Comments

@JakeQuilty
Copy link
Contributor

Is your feature request related to a problem? Please describe.

There is no demo for the docker registry generic connector.

Describe the solution you would like

Create a demonstration of the docker registry generic connector in action. The goal is to have the demo flow around a Jenkins server hosted in Kubernetes that authenticates with Secretless to push and pull from a private Docker Registry.

Describe alternatives you have considered

Additional context

This stems from this Epic to create more generic connector examples.

@JakeQuilty
Copy link
Contributor Author

Notes

After a lot of trial and error, I decided to drop the Kubernetes part of this tutorial. It was over complicating it and creating tons of problems. I decided to pivot to a docker-compose file to stand up the environment.

The initial workflow of using the generic connector to authenticate for push/pulling images to/from a Docker Registry does not seem like a practical example of maintaining images in a Jenkins pipeline. I'm looking into other possible ways of using Secretless to authenticate with Docker to make the tutorial

@izgeri
Copy link
Contributor

izgeri commented Jul 17, 2020

@JakeQuilty can you share more details about what you're looking into? If I connect to a remote Docker registry now, I unfailingly use the CLI (I never make direct API calls) - is there a way to configure the CLI to connect to Secretless as if it's the remote registry, and have Secretless add the correct headers to the requests Secretless sends? Is that doable with the generic connector, or would a more flexible custom connector be needed for this use case? The more details you can add, the better we'll be able to understand how to push this forward.

@JakeQuilty
Copy link
Contributor Author

JakeQuilty commented Jul 17, 2020

Update

After a lot of playing with the CLI, I'm not sure if this is practical with the way the CLI authenticates the user on docker login.

The CLI requires a user to be "logged in" before making a docker push or docker pull command through the CLI. The CLI stores the "logged in" registry in ~/.docker/config.json and stores the users username and password in the specified credential store in the same ~/.docker/config.json under "credsStore": (the default for OS X is desktop which is the OS X Keychain). If you delete the credsStore parameter, it will store the credentials unencrypted as a parameter in the specific registry you logged into as a base64 formatted "auth": "username:password".

"Logged in" can be defined as: having a registry specified in the config.json with either a credsStore specified, OR an auths sub-param in the registry item.

The Docker CLI feeds these credentials straight, the way they are, to the Docker Daemon. The Docker Daemon then authenticates to the Registry by, from everything I've seen, sending the credentials to the Registry and receiving a Bearer Token on every CLI request that goes out to the Registry. This article was really helpful for describing how the CLI authenticates. The MiTM the author uses makes Secretless seem possible between the Daemon and the Registry. I have not been able to set up a proxy for the Daemon on OS X and I found this thread that confirmed it wasn't possible(after hours of trying).

I haven't been able to test this on a Linux VM yet, because I ran out of time for the day.

Regardless if Secretless can be hacked into a proxy between the Docker Daemon and the Registry, I think the set up required to do this might kill the ability to scale it through Jenkins servers in containers. The only way I was able to trick the CLI into allowing a CLI command that required authentication to go through to the Daemon was by deleting the default credsStore and adding the registry address manually to the config.json.

Credential Helpers

After looking at this for a while, I think a good way to achieve the same goal of keeping the Docker credentials off of the Jenkins server would be to use Conjur as a Docker credential helper. This does not seem too difficult to implement and would keep the credentials off the Jenkins server until they are used. These are just binaries that are called to store, get, erase, and list the credentials for each Registry. On OS X these are stored in /Applications/Docker.app/Contents/Resources/bin.

@JakeQuilty
Copy link
Contributor Author

Update

I don’t think this is possible without making a specific connector for HTTP. In an Ubuntu vm I was able to put a Secretless proxy between the daemon and the registry. I used this blog about Docker Authentication again and this Docker doc to set it up.

$ cat /etc/systemd/system/docker.service.d/http-conf.conf
[Service]
Environment=“HTTP_PROXY=http://localhost:8021”
Environment=“HTTPS_PROXY=https://localhost:8021”

I used the generic HTTP config for Docker Registries. Unfortunately, when trying to docker login or docker pull(commands that require auth with the registry) I got this error:

$ docker pull jacobquilty/test-private
Using default tag: latest
Error response from daemon: Get https://registry-1.docker.io/v2/: proxyconnect tcp: tls: first record does not look like a TLS handshake

I don’t think generic HTTP connectors will work OOB with the Docker CLI, because of how the daemon authenticates with the Registry.

Suggested Solution

We should make a specific connector for Docker CLI. There are two places to put Secretless to authenticate with the Docker CLI.

Docker CLI --> Secretless --> Docker Daemon

The Docker daemon default listens on this sock: unix:///var/run/docker.sock that the CLI sends its commands to. This can be changed by following BIND DOCKER TO ANOTHER HOST/PORT OR A UNIX SOCKET(scroll down, there was no anchor on that part). Here we could inject the username and password for the Registry user. The format for these creds is mentioned in my first comment. I’m not too familiar with socks, so I’m not sure how practical this is for remote Secretless servers, but it’s an option.

Docker Daemon --> Secretless --> Docker Registry

For this we’d use an HTTP connector to inject the Bearer token into the request to the Registry. We’d have to work around credential handshake that the Daemon and Registry do to get the API token. I spent most of my time looking at this, so most of my notes give more details about this.

@JakeQuilty
Copy link
Contributor Author

Putting this on hold until there is a Docker CLI connector. I created a new issue to create the connector here: #1312

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants