Lei Mao bio photo

Lei Mao

Machine Learning, Artificial Intelligence, Computer Science.

Twitter Facebook LinkedIn GitHub   G. Scholar E-Mail RSS

Introduction

When we run docker login, we will often see a warning message that our password is saved encrypted in the Docker configuration file.


The warning might be ignored if the account and password to the operating system is not shared with others. However, if it is a shared account, docker login might put your docker account and password in danger. If we check the JSON file, we would find there is an unencrypted representing our password there.

$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: leimao
Password: 
WARNING! Your password will be stored unencrypted in /home/leimao/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

# Passwork saved as an unencrypted string in "auth".
$ cat /home/leimao/.docker/config.json
{
	"auths": {
		"https://index.docker.io/v1/": {
			"auth": "xxxxxxxxxxxxxxxxxxxxxxxx"
		}
	},
	"HttpHeaders": {
		"User-Agent": "Docker-Client/19.03.12 (linux)"
	}
}

# Docker logout to remove the saved credentials.
$ docker logout

What we need to do is to follow the credentials store guideline from Docker, install and configure one of the credentials helpers, and encrypt our password.


In this blog post, I would like to briefly go over the credentials encryption set up for docker login.

Docker Login Credentials Encryption

In my case, because I am a Linux user, so I chose to use pass as my credentials helper.

$ cat /home/leimao/.docker/config.json
{
	"auths": {},
	"HttpHeaders": {
		"User-Agent": "Docker-Client/19.03.12 (linux)"
	}
}

# Install the standard Unix password manager.
$ sudo apt-get install pass

# Download and install docker-credential-pass.
# The latest version is v0.6.3.
$ cd ~/Downloads/
$ wget https://github.com/docker/docker-credential-helpers/releases/download/v0.6.3/docker-credential-pass-v0.6.3-amd64.tar.gz
$ tar -xvf docker-credential-pass-v0.6.3-amd64.tar.gz
# Open ~/.bashrc to modify the $PATH or move the docker-credential-pass to the $PATH.
$ sudo rm /usr/bin/docker-credential-pass
$ sudo mv docker-credential-pass /usr/bin/
$ chmod +x /usr/bin/docker-credential-pass

# Docker credentials helper have no credentials saved yet.
$ docker-credential-pass list
{}

# This might be necessary if the following step hangs forever.
# $ sudo apt-get install rng-tools

# Generate encryption keys.
$ gpg --generate-key
gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name: leimao
Email address: dukeleimao@gmail.com
You selected this USER-ID:
    "leimao <dukeleimao@gmail.com>"

Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
# Following the instruction to reate the password to the user ID. 

# Initialize the password manager for the encryption key.
$ pass init dukeleimao@gmail.com
mkdir: created directory '/home/leimao/.password-store/'
Password store initialized for dukeleimao@gmail.com

$ cat /home/leimao/.password-store/.gpg-id 
dukeleimao@gmail.com

# Add "credsStore": "pass" to the JSON file.
# So that Docker knows it has to use docker-credential-pass to manage credentials.
$ vim ~/.docker/config.json

# Now we could safely login.
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: leimao 
Password: 
Login Succeeded

$ docker-credential-pass list
{"https://index.docker.io/v1/":"leimao"}

# The password is no longer saved in the Docker configuration.
$ cat ~/.docker/config.json
{
	"auths": {
		"https://index.docker.io/v1/": {}
	},
	"HttpHeaders": {
		"User-Agent": "Docker-Client/19.03.12 (linux)"
	},
	"credsStore": "pass"
}

Caveats

If we happen to screw anything up, we could restart by deleting the related files.

$ rm -rf ~/.docker/ ~/.password-store/ ~/.gnupg/

In some scenarios, especially when we SSH remotely, even with the Docker credentials helper correctly set up, we might still not be able to access the content in the Docker registry.

$ docker pull leimao/xxxxx:1.0
Error response from daemon: pull access denied for leimao/xxxxx, repository does not exist or may require 'docker login': denied: requested access to the resource is denied

This is because gpg was not correctly invoked. This could be resolved by setting the environment variable GPG_TTY.

$ export GPG_TTY=$(tty)

If you are curious about what tty is, you might check via the following command.

$ tty --help
Usage: tty [OPTION]...
Print the file name of the terminal connected to standard input.

References