Recommended way to configure registry credentials for private Docker Hub repos

With Drone 0.7 on the server side, and drone version 0.5.0+dev on the CLI side, I’ve been trying to configure drone to pull an image from my private Docker Hub repository.

But I haven’t been successful in getting past the ERROR: Error response from daemon: repository [my repo] not found: does not exist or no pull access error in my build logs.

I noticed that the docs contain a few different approaches to doing this - so I’m wondering if I’m overlooking the preferred way to accomplish this in 0.7.

What I’ve tried so far:

I’ve attempted to follow that guide, and used drone secret add to add a DOCKER_PASSWORD secret to my repository. I then updated the .drone.yml in my git repo to use password: ${DOCKER_PASSWORD} for auth. I still get the does not exist or no pull access error when drone tries to pull my docker hub image, though.

  • Adding secrets for my repo in the UI - I noticed secrets can be added in the UI, so I tried adding secrets to my project (I named them REGISTRY_USERNAME and REGISTRY_PASSWORD, and removed the username and password lines from my .drone.yml). This still didn’t seem to help, though.

  • I tried following http://readme.drone.io/0.5/download-private-docker-images-secrets/

No luck with that approach either - although maybe the doc doesn’t apply to the latest version of the CLI, since I see it mentions drone secrets, while the subcommand seems to have been changed to drone secret?

  • I tried using the drone CLI and drone registry add, following this page in the docs:

http://docs.drone.io/manage-registry-credentials/

However, with the version of the drone CLI that I’m running (drone version 0.5.0+dev), the drone registry subcommand doesn’t seem to exist:

# drone registry -h
No help topic for 'registry'

Is there a recommended way to add Docker Hub credentials in drone 0.7 besides the approaches I mentioned above? I’d like to avoid putting the credentials into my .drone.yml.

Thanks!

2 Likes

Hi Bill,

The canonical documentation for providing registry credentials are here (as you mentioned):
http://docs.drone.io/manage-registry-credentials/

This documented approach is the only way to configure registry credentials in 0.7 or higher. Approaches that worked for previous versions of Drone, including using secrets, will no longer work in 0.7 or higher.

This tells me you have an outdated version of the CLI

$ drone registry --help
NAME:
   drone registry - manage registries

USAGE:
   drone registry command [command options] [arguments...]

COMMANDS:
     add     adds a registry
     rm      remove a registry
     update  update a registry
     info    display registry info
     ls      list regitries

OPTIONS:
   --help, -h  show help

Please ensure you install the CLI per the install guide:
http://docs.drone.io/cli-installation/

1 Like

Thanks! Looks like the old CLI was the problem. When I began googling around for drone cli I probably landed at http://readme.drone.io/0.5/install/cli/, and thus ended up with the 0.5 CLI release.

Looks like all I had to do was to install the 0.7 CLI via the page you mentioned, then this made everything work:

drone registry add \
  --repository my/repo \
  --hostname docker.io \
  --username <foo> \
  --password <bar>

Excellent glad you got it working :slight_smile:

Note that we have 0.8.0-rc.5 which includes the ability to manage registry credentials in the user interface as well. The final release is planned for Monday, assuming we do not discover any critical issues in the mean time.

Hello @bradrydzewski, are there any plans to encrypt the registry credentials in the database? Using the postgre backend, I can see the passwords for registry logins stored in plaintext.

I don’t know how secrets are stored (binary data) and if they are encrypted, but would it be possible to store the registry passwords the same way?

Is using postgres disk encryption an option?

If you are a drone administrator you will need to set a decryption key, which means you will still have access to the secrets in plan text.

I’m afraid not, the postgres database is an AWS instance. This is also true if I try to store the registry credentials using sqlite, so I assume it will be true for any database driver

But even with disk encryption, this would not solve the problem I was hinting at, maybe I did not explain it properly, so I’ll try again :slight_smile: I am also not sure what you meant by decryption key (is this in any way related to DRONE_SECRET env)? Because the way secrets are stored is fine as far as I am concerned, no issue there :slight_smile:

I can think of two cases in which this would be a problem:

The not so big issue would be:

  • The database admin is not supposed to have access to private docker registry
  • However (s)he could read this from the database once drone stores it there

Or the worse scenario:

  • Imagine a case when a database administrator’s computer is compromised
  • His/her db login credentials are stolen
  • Besides this being a problem by itself, it also opens another attack vector, because the attacker is able to read docker registry credentials from drone database (because they are stored in plain text)
  • The private registries are now compromised as well and the attacker can download all of our private images, eventually delete them if allowed

Therefor I think the passwords to registries should be encrypted in some way… possibly using the same algorithm which stores secrets (using the DRONE_SECRET env?). For this reason, I also think this should be drone’s responsibility to encrypt the password

In case this does not make the 0.8.0 release, I think it should be noted in the changelog and if possible in the docs as well so admins know this before updating and letting drone store the credentials. I slightly remember a quote which said something along the lines of

It is better to know you are not protected than to presume you are

Too bad I can’t remember where it was, some security talk for sure :slight_smile:

Would you agree an issue should be created for this?

We discussed this a while back in our gitter channel (which no longer exists) so I can try to summarize here. I think it is important to assess all different vectors to determine if and when encryption would effectively protect your information.

Here are some different scenarios we can consider:

#1 Default Configuration, Drone Server Compromised

If you are using the default drone configuration, encrypting specific database fields does not really make sense. This is because the default drone configuration uses sqlite. If you have access to the sqlite file, you have access to the server, which means you have access to the decryption key. Encryption of columns in a sqlite database would be for vanity purposes only.

ENCRYPTION NOT EFFECTIVE

#2 Local Postgres Database, Drone Server Compromised

If you are running the Drone server and Postgres database on the same machine, and an attacker compromises the server, they will have access to the raw database, the database credentials (provided to drone) and the database decryption keys.

ENCRYPTION NOT EFFECTIVE

#3 Remote Postgres Database, Drone Server Compromised

If someone compromises your drone server and you are using a remote Postgres database, they will still have access to your database username, password and decryption key.

ENCRYPTION NOT EFFECTIVE

#4 Remote Postgres Database, Database Server Compromised

If you are using a remote Posgres database and someone compromises your laptop, hopefully your database administrator is following some best practices some of which are enforced by default when using aws

  • laptop has a username and password
  • laptop has disk encryption
  • you are using aws security groups
  • you are limiting database access by IP

If your database server is compromised and the attacker is able to subvert these security precautions, they will have access to your database details including secrets and registry credentials. In this case per-column encryption would be effective.

ENCRYPTION EFFECTIVE, however, this vector should not be possible if you are using default, industry standard practices to limit database access by IP address.

#5 Malicious Database Administrator

If your database administrator also has access to the drone server, they will have access to the drone encryption key and will therefore be able to decrypt your database. Lets assume, however, the database administrator only has access to the database.

The database administrator would have access to your database details including secrets and registry credentials. In this case per-column encryption would be effective. Note that you could use alternate storage mechanisms for secrets (such as vault) but otherwise this is a vector that could benefit from column-level encryption.

ENCRYPTION_EFFECTIVE

Would you agree an issue should be created for this?

Based on the above assessment I believe per-column database encryption would be most effective in preventing vector 5. However, if an attacker compromises your Drone server this really won’t matter.

So do I plan on implementing encrypted columns in Drone?

I do not. Column-level encryption does not eliminate a major attack vector (gaining access to the drone server) and will never be as secure as something like Vault, which is explicitly designed to store sensitive information (support shamir’s secret sharing, key rotation, etc). Instead, I prefer to remove secrets from the Drone database entirely and require teams use secret managers (vault, aws secrets manager, kubernetes secret manager). Vault is already supported. Stay tuned for more changes in 0.9.

3 Likes

Thank you for the summary Brad.

I believe that once a server is compromised (with drone or anything else), it is pretty much a game over for whatever the application relies on…well in most cases. This is also a reason why I am always trying to separate the database from the application (where aws comes very handy)

I will discuss this with my colleague as this is probably one of the things which will prevent our company from migrating to 0.8.0

If need be, I will create an issue and see if we find time to come up with a PR