docker-credential-helpers icon indicating copy to clipboard operation
docker-credential-helpers copied to clipboard

Document how to initialize docker-credentials-pass

Open pasih opened this issue 7 years ago • 78 comments

Hi,

the README currently says: "pass needs to be configured for docker-credential-pass to work properly. It must be initialized with a gpg2 key ID. Make sure your GPG key exists is in gpg2 keyring as pass uses gpg2 instead of the regular gpg."

However, I could not find any documentation whatsoever on the initialization. There doesn't seem to be a docker-credentials-pass init command? It would be helpful to actually document the steps how to initialize the pass store.

(I can create a pull request for README changes once I figure out how to actually do the initialization)

pasih avatar May 11 '18 07:05 pasih

Hi. I`m sorry for my English. After spending some time, i was able to setup credential store and maybe my experience will help you.

I used ubuntu 18.04 and did all action as root user.

  1. download "docker-credential-pass". wget https://github.com/docker/docker-credential-helpers/releases/download/v0.6.0/docker-credential-pass-v0.6.0-amd64.tar.gz

  2. unpack tar -xf docker-credential-pass-v0.6.0-amd64.tar.gz

  3. i couldn`t configure $PATH environment variable, so i copied unpacked file to /usr/bin directory.

  4. check that docker-credential-pass work. To do this, run command docker-credential-pass. You should see: "Usage: docker-credential-pass <store|get|erase|list|version>".

  5. install gpg and pass. apt install gpg pass

  6. gpg --generate-key. Enter your name, mail, etc. You will get gpg-id like "5BB54DF1XXXXXXXXF87XXXXXXXXXXXXXX945A". Copy it to clipboard.

  7. pass init (paste from clipboard)

  8. pass insert docker-credential-helpers/docker-pass-initialized-check and set the next password "pass is initialized" (without quotes).

  9. pass show docker-credential-helpers/docker-pass-initialized-check. You should see pass is initialized.

  10. docker-credential-pass list. You should see {} or another data. You shouldn`t see error like "pass store is uninitialized".

  11. nano ~/.docker/config.json. Set in root node the next line "credsStore": "pass" save ctrl+o.

  12. after docker login and etc.

I'm not a guru on unux based OS and some actions can be done better. I hope someone will help my answer.

Ayrat-Kh avatar May 13 '18 15:05 Ayrat-Kh

@pasih, here is what i did to get my docker client working with docker-credentials-pass. I have slight variations from what @Ayrat-Kh did.

  1. Install pass
sudo apt-get install pass
  1. Download, extract, make executable, and move docker-credential-pass
wget https://github.com/docker/docker-credential-helpers/releases/download/v0.6.0/docker-credential-pass-v0.6.0-amd64.tar.gz && tar -xf docker-credential-pass-v0.6.0-amd64.tar.gz && chmod +x docker-credential-pass && sudo mv docker-credential-pass /usr/local/bin/
  1. Create a new gpg2 key.
gpg2 --gen-key
  1. Follow prompts from gpg2 utility

  2. Initialize pass using the newly created key

pass init "<Your Name>"
  1. Add credsStore to your docker config. This can be done with sed if you don't already have credStore added to your config or you can manually add "credStore":"pass" to the config.json.
sed -i '0,/{/s/{/{\n\t"credsStore": "pass",/' ~/.docker/config.json
  1. Login to docker
docker login

References: https://hackernoon.com/getting-rid-of-docker-plain-text-credentials-88309e07640d https://www.passwordstore.org/

nathanfiscus avatar May 14 '18 21:05 nathanfiscus

Another slight variation, as I needed to use /dev/urandom apparently I was running out of entropy and gpg2 --gen-key was hanging on the "generating random numbers .... " part

wget https://github.com/docker/docker-credential-helpers/releases/download/v0.6.0/docker-credential-pass-v0.6.0-amd64.tar.gz && tar -xf docker-credential-pass-v0.6.0-amd64.tar.gz && chmod +x docker-credential-pass && sudo mv docker-credential-pass /usr/local/bin/

yes | sudo apt install pass
yes | sudo apt install rng-tools
yes | sudo apt install rng-tools5
gpg-agent --daemon --use-standard-socket --pinentry-program /usr/bin/pinentry-curses
sudo rngd -r /dev/urandom
gpg2 --gen-key
pass init "Your Name"
sed -i '0,/{/s/{/{\n\t"credsStore": "pass",/' ~/.docker/config.json
docker login your-registry:5000

visualex avatar May 29 '18 15:05 visualex

  1. pass insert docker-credential-helpers/docker-pass-initialized-check and set the next password "pass is initialized" (without quotes).
  2. pass show docker-credential-helpers/docker-pass-initialized-check. You should see pass is initialized.
  3. docker-credential-pass list. You should see {} or another data. You shouldn`t see error like "pass store is uninitialized".

I had to follow these steps of @Ayrat-Kh's to get docker-credential-pass list to print anything other than "pass store is uninitialized". After doing this, though, I was able to rm ~/.password-store, run pass init $ID again, and have it as expected, without having to do steps 8-10 again.

CodingKoopa avatar Jun 27 '18 20:06 CodingKoopa

If the passphrase is not empty while generating gpg key, got following error message when running docker login your-registry:5000 with version v0.6.1.

Error saving credentials: error storing credentials - err: exit status 1, out: `error fetching password during initialization: exit status 2: gpg: cancelled by user
gpg: decryption failed: No secret key`

The error was thrown by pass_linux.go#L64 which the script is trying to run

pass show ~/.password-store/docker-pass-initialized-check

Caused by a prompt popped out for asking the passphrase, due to there is no input, error message exit status 2: gpg: cancelled by user was caught.

Thus, entering passphrase by running the command above manually could temporally solve the problem.

edingroot avatar Jul 26 '18 02:07 edingroot

@nathanfiscus thanks for the steps mentioned https://github.com/docker/docker-credential-helpers/issues/102#issuecomment-388974092, I didn't find it was very clear from the docs at https://github.com/docker/docker-credential-helpers/issues/102 - I did the extra step of downloading the docker-credentials-pass and it worked fine. I'm thinking docker-credentials-pass is the wrapper around pass so we need both of them present

:+1: :heart:

neomatrix369 avatar Aug 06 '18 15:08 neomatrix369

@nathanfiscus Excellent. Thanks for the steps. I would like to handle entering the passphrase through bash script for the following command. pass show ~/.password-store/docker-pass-initialized-check Is it possible?

krisbalaa avatar Aug 16 '18 12:08 krisbalaa

If you follow this guide and somehow you can't generate gpg key because gpg process is hanging, please install rng-tools and run its deamon by rngd -r /dev/urandom to generate enough random noise in your system to generate the key. You can observe your noise by cat /proc/sys/kernel/random/entropy_avail. Also using gnupg2 could help.

mkjmdski avatar Sep 25 '18 07:09 mkjmdski

Hi. I`m sorry for my English. After spending some time, i was able to setup credential store and maybe my experience will help you.

I used ubuntu 18.04 and did all action as root user.

  1. download "docker-credential-pass". wget https://github.com/docker/docker-credential-helpers/releases/download/v0.6.0/docker-credential-pass-v0.6.0-amd64.tar.gz
  2. unpack tar -xf docker-credential-pass-v0.6.0-amd64.tar.gz
  3. i couldn`t configure $PATH environment variable, so i copied unpacked file to /usr/bin directory.
  4. check that docker-credential-pass work. To do this, run command docker-credential-pass. You should see: "Usage: docker-credential-pass <store|get|erase|list|version>".
  5. install gpg and pass. apt install gpg pass
  6. gpg --generate-key. Enter your name, mail, etc. You will get gpg-id like "5BB54DF1XXXXXXXXF87XXXXXXXXXXXXXX945A". Copy it to clipboard.
  7. pass init (paste from clipboard)
  8. pass insert docker-credential-helpers/docker-pass-initialized-check and set the next password "pass is initialized" (without quotes).
  9. pass show docker-credential-helpers/docker-pass-initialized-check. You should see pass is initialized.
  10. docker-credential-pass list. You should see {} or another data. You shouldn`t see error like "pass store is uninitialized".
  11. nano ~/.docker/config.json. Set in root node the next line "credsStore": "pass" save ctrl+o.
  12. after docker login and etc.

I'm not a guru on unux based OS and some actions can be done better. I hope someone will help my answer.

@Ayrat-Kh Sorry, but where did you get this "secret knowledge" from?)

olekszhel avatar Nov 09 '18 15:11 olekszhel

Hi using Fedora 28 and Docker version 18.09.0, build 4d60db4.

pass is not the password store by default. Docker stores passwords bas64 encoded. The instructions above by @Ayrat-Kh and @nathanfiscus are not working for me. I keep getting the error:

Error saving credentials: error storing credentials - err: exit status 1, out: \pass store is uninitialized``

Here's my output after @Ayrat-Kh steps:

pass llst

Password Store
└── docker-credential-helpers
    └── docker-pass-initialized-check

pass show docker-credential-helpers/docker-pass-initialized-check

pass is initialized

I see the plan is to add pass as default

https://github.com/docker/docker-ce/commit/9337e1311395ec064c5f1af48f910cd4abc017c5

but right now I can't get it working

ghost avatar Dec 16 '18 20:12 ghost

any ideas? @n4ss

ghost avatar Dec 16 '18 20:12 ghost

@jmliz I was able to solve this by running

pass insert docker-credential-helpers/docker-pass-initialized-check

and then not setting a passphrase. I just left it empty

It has been working since.

makville avatar Dec 26 '18 18:12 makville

@makville I'm still getting the same error with an empty passphrase.

ghost avatar Dec 26 '18 19:12 ghost

I'm getting the same error, I followed the steps for docker-credential-helper, they worked the 1st time, but after restarting the computer, same behavior continues, even if I retrace the steps for generating keys and docker login, as soon as I hit docker-compose up , I get the credentials error :(

dabiddo avatar Jan 01 '19 00:01 dabiddo

@jmliz @dabio I just experienced the same problem as you. Once I restarted the server it was all back to square one again. Oh well.

makville avatar Jan 01 '19 13:01 makville

@makville restarting doesn't help. I wasn't ever able to get it working in the first place.

ghost avatar Jan 01 '19 13:01 ghost

this plugin doesn't even have proper documentation. no contributor ever replied to this issue.

ghost avatar Jan 01 '19 13:01 ghost

Those of you still having issues might try one of these below. I haven't looked through all the code for docker-credential-pass, but I think that the plugin is not properly triggering the gpg-agent (in all instances) that pass uses to login to and decrypt the store. Essentially the password store is locking after the default 10 minutes. I have two workarounds for this until/if the issue gets fixed:

  1. Set the timeout for the gpg-agent conf to a ridiculously high number:
$ cat ~/.gnupg/gpg-agent.conf
max-cache-ttl 60480000
default-cache-ttl 60480000

That is 400 days. This obviously is just as insecure as using the default plain text file, but gets around the warning. You will have to trigger this the first time and after 400 days or whatever you set.

  1. Manually trigger the pass store to unlock before performing a docker command that requires authentication like docker login or docker push. I have been experimenting with this bash script (this is a work in progress and bash is not a strength of mine, so feel free to clean this up. 😄)
INITMSG="$(pass show docker-credential-helpers/docker-pass-initialized-check)"
ERRMSG="Error"
LISTMSG=""

if [ "$INITMSG" = *$ERRMSG* ]
then
LISTMSG="$(docker-credential-pass list)"
else
LISTMSG="Initialized"
fi

ERRMSG2="pass store is uninitialized"
EMPTY=""

if [ "$LISTMSG" = "$ERRMSG2" ]
then
exit 1
elif [ "$LISTMSG" = "$EMPTY" ]
then
exit 1
else
exit 0
fi

I put this in my /usr/bin directory and made it executable.

Usage would be something like:

docker-pass && docker login

nathanfiscus avatar Jan 08 '19 17:01 nathanfiscus

@nathanfiscus I don't understand when you say "Essentially the password store is locking after the default 10 minutes". I immediately try to login after I set up pass and it doesn't work. I will give it a try though.

ghost avatar Jan 08 '19 20:01 ghost

I also have issues using this even immediately afterwards running docker-credential-pass list and getting {} returned.

In my case I can run docker login and it works, but it seems that the password is not actually saved into the store, and when I docker logout I get an error about it not being there, and sure enough, another list still shows everything as empty.

Maybe it depends on the version of Docker you are running? Newer versus older?

I have:

  • gpg (GnuPG) 2.2.7
  • pass version v1.7.3
  • tree v1.8.0 # which is needed by pass unfortunately.
  • Docker version 18.06.1-ce, build e68fc7a
  • docker-credential-pass 0.6.0

In my case I am building everything, but Docker and GnuPG, as I am trying to get this working on a CoreOS linux system.

spkane avatar Jan 10 '19 19:01 spkane

I figured out the issue in my case. This still feels a bit like a bug, but of a different sort. Using docker login against a registry that does not currently support auth (we are turning it on in a few days after some testing) works fine. It seems to log you in no matter what you use as the username/password, but docker logout breaks, as no credential is stored during login, so when you logout, and it tries to deleted the credential you get an error saying that the credential delete failed.

spkane avatar Jan 11 '19 16:01 spkane

@spkane how can login work if you dont have authentication? I'm not aware of docker internals but that sounds strange. nothing worked so far for me.

ghost avatar Jan 11 '19 17:01 ghost

TL;DR: It works when user is in docker group, but when using docker with sudo this messes up the credential handling. The docker login command then looks in /root/ where pass is not initialized which leads to the error message Error saving credentials: error storing credentials - err: exit status 1, out: 'pass store is uninitialized'.

@nathanfiscus @Ayrat-Kh @CodingKoopa @visualex : Can you verify you are part of docker group? @jmliz @dabiddo @makville : Does this help you getting it to work?

Setup and running solution

Here is what I tried followed by the measured to actually get it to work:

  1. Install gpg and pass

    sudo pacman -S gnupg2 pass
    
  2. Follow interactive prompt to generate gpg key pair

    gpg --full-gen-key
    
    Full output of the above command
    $ gpg --full-gen-key
    gpg (GnuPG) 2.2.12; Copyright (C) 2018 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.
    
    Please select what kind of key you want:
      (1) RSA and RSA (default)
      (2) DSA and Elgamal
      (3) DSA (sign only)
      (4) RSA (sign only)
    Your selection? 1
    RSA keys may be between 1024 and 4096 bits long.
    What keysize do you want? (2048) 2048
    Requested keysize is 2048 bits
    Please specify how long the key should be valid.
            0 = key does not expire
          <n>  = key expires in n days
          <n>w = key expires in n weeks
          <n>m = key expires in n months
          <n>y = key expires in n years
    Key is valid for? (0) 12m
    Key expires at So 12 Jan 2020 17:59:43 CET
    Is this correct? (y/N) y
    
    GnuPG needs to construct a user ID to identify your key.
    
    Real name: [USER_NAME]
    Email address: [MAIL_ADDRESS]
    Comment:
    You selected this USER-ID:
        "[USER_NAME] <[MAIL_ADDRESS]>"
    
    Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    gpg: key [KEY_ID] marked as ultimately trusted
    gpg: directory '$HOME/.gnupg/openpgp-revocs.d' created
    gpg: revocation certificate stored as '$HOME/.gnupg/openpgp-revocs.d/[KEY_FINGERPRINT].rev'
    public and secret key created and signed.
    
    pub   rsa2048 2019-01-17 [SC] [expires: 2020-01-12]
          [KEY_FINGERPRINT]
    uid                      [USER_NAME] <[MAIL_ADDRESS]>
    sub   rsa2048 2019-01-17 [E] [expires: 2020-01-12]
    
  3. Initialize pass

    $ pass init [KEY_FINGERPRINT]
    mkdir: created directory '$HOME/.password-store/'
    Password store initialized for [KEY_FINGERPRINT]
    
  4. Download docker-credential-pass and put it in /usr/local/bin/ which is in $PATH (credit to David Rieger HackerNoon)

    wget https://github.com/docker/docker-credential-helpers/releases/download/v0.6.0/docker-credential-pass-v0.6.0-amd64.tar.gz && tar -xf    docker-credential-pass-v0.6.0-amd64.tar.gz && chmod +x docker-credential-pass && sudo mv docker-credential-pass /usr/local/bin/ && rm    docker-credential-pass-v0.6.0-amd64.tar.gz
    
  5. Add credsStore to $HOME/.docker/config.json (credit to David Rieger HackerNoon)

    sed -i '0,/{/s/{/{\n\t"credsStore": "pass",/' ~/.docker/config.json
    
  6. Login with docker login

Info: The following shows two different scenarios of which 1) is running out of the box 2) fails.

  1. User is part of docker group

    $ docker login [URL_TO_PRIVATE_DOCKER_REGISTRY]
    Username: [USER_NAME]
    Password:
    Login Succeeded
    
    # logout and log back in
    
    $ docker login [URL_TO_PRIVATE_DOCKER_REGISTRY]
    Authenticating with existing credentials...
    Login Succeeded
    
    $ pass
    Password Store
    └── docker-credential-helpers
        └── [CRED_FOLDER_NAME]
            └── [USER_NAME]
    
    $ docker logout [URL_TO_PRIVATE_DOCKER_REGISTRY]
    Removing login credentials for [URL_TO_PRIVATE_DOCKER_REGISTRY]
    WARNING: could not erase credentials: error erasing credentials - err: exit status 1, out: `exit status 1: Error: docker-credential-helpers/[CRED_FOLDER_NAME] is not in the password store.`
    
    $ pass
    Password Store
    

    As can be seen from the output above, the tool works as intended and adds credentials to pass. Removing credentials from pass with docker logout [PATH_TO_PRIVATE_DOCKER_REGISTRY] throws an error, but actually removes the credentials from pass.

    ==> Successfully logged in and stored credentials in pass

  2. Using docker with sudo

    $ sudo docker [URL_TO_PRIVATE_DOCKER_REGISTRY]
    Username: [USER_NAME]
    Password:
    Error saving credentials: error storing credentials - err: exit status 1, out: `pass store is uninitialized`
    

    Using docker without sudo in this setup will throw an error because of missing permissions for the socket: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.39/auth: dial unix /var/run/docker.sock: connect: permission denied

    ==> Fails to login successfully

Fix the problem temporarily

Warning: The docker group grants privileges equivalent to the root user. For details on how this impacts security in your system, see Docker Daemon Attack Surface.

Now, people who prefer to not add users to the docker group might have to wait until this is fixed in the tool itself. For everyone else, simply add the user to docker group and restart the session (logout and log back in) so the new group setting take effect.

sudo gpasswd -a $USER docker

# logout and log back in

$ docker login [URL_TO_PRIVATE_DOCKER_REGISTRY]
Username: [USER_NAME]
Password:
Login Succeeded

Shortcomings of documentation

I found the documentation is lacking Information for users that might not have been working with credential stores like pass before. For me it was not even clear whether those tools are included in the docker installation or have to be downloaded from GitHub. The only hin given is 'Docker requires the helper program to be in the client’s host $PATH.' which implicitly let's the user know that she has to take action and thus probably download the tool first.

Nevertheless, after going through the documentation of gpg and pass to learn how to set everything up, I was quite frustrated to still see it not working. I followed the steps of @Ayrat-Kh mentioned in his comment without success.

Setup

  • OS: Manjaro
  • gpg: 2.2.12
  • pass: v1.7.3
  • docker: 18.09.0-ce, build 4d60db472b
  • docker-credential-pass: v0.6.0

Sources

  1. https://hackernoon.com/getting-rid-of-docker-plain-text-credentials-88309e07640d
  2. https://www.passwordstore.org
  3. https://www.digitalocean.com/community/tutorials/how-to-use-gpg-to-encrypt-and-sign-messages

bentocin avatar Jan 17 '19 21:01 bentocin

I have read through all the replies and still can't get the credential helper to work. I already had pass installed and am using it regularly.

$ pass show docker-credential-helpers/docker-pass-initialized-check
pass is initialized
# The above was already there, so looks like docker-credential-pass was able to write at least.

$ groups
users wheel disk audio video docker

$ docker-credential-pass list
pass store is uninitialized

$ cat ~/.docker/config.json
{
        "credsStore": "pass",
        ...
}

$ docker-credential-pass version
0.6.0

$ pass --version
============================================
= pass: the standard unix password manager =
=                                          =
=                  v1.7.2                  =
=                                          =
=             Jason A. Donenfeld           =
=               [email protected]            =
=                                          =
=      http://www.passwordstore.org/       =
============================================

$ docker --version
Docker version 18.06.1-ce, build e68fc7a215d7133c34aa18e3b72b4a21fd0c6136

$ 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: XXX
Password:
Error saving credentials: error storing credentials - err: exit status 1, out: `pass store is uninitialized`

OS: Nix OS.

Legogris avatar Feb 19 '19 16:02 Legogris

@bentocin to make docker-credential-pass working when the user is not in docker group, you can also do:

  1. switch to root: $ sudo su
  2. do all the steps you mention as root

damienrg avatar Mar 22 '19 13:03 damienrg

I had a case where I need to automate this with jenkins CI. I've written up the approach I ended up taking for CentOS and docker-credential-helpers. I'm far from an expert and no doubt it won't match everyones needs but it appears to be working for us and hope it's of some help to others in the meantime: credentials-management.md

dataday avatar Apr 10 '19 13:04 dataday

It appears that docker-credential-helpers can easily reach a state where it has marked the pass path as initialised, and this can be hard to reset. I found the following to work:

pass rm -r docker-credential-helpers
pass init -p docker-credential-helpers <GPGID>

pass ls
Password Store
└── docker-credential-helpers

docker login <registry>
Username: <username>
Password: <password>

$ pass ls
Password Store
└── docker-credential-helpers
    └── <CREDHASH>
        └── <username>

javabrett avatar Apr 17 '19 05:04 javabrett

OK here's another essential tip if you find your pass repo constantly corrupted by incomplete docker-pass-initialized-check:

export GPG_TTY=$(tty)

... so that gpg properly prompts for key passphrase, assuming you have one.

javabrett avatar Apr 17 '19 06:04 javabrett

@javabrett

pass init -p docker-credential-helpers <GPGID>

-p is not a valid flag to pass init

$ pass init -p docker-credential-helpers <GPGID> pass: invalid option -- 'p' Usage: pass init [--reencrypt,-e] gpg-id

mcallaghan-bsm avatar Apr 27 '19 02:04 mcallaghan-bsm

@mcallaghan-bsm which platform/version are you running?

tee Dockerfile <<EOF
> FROM debian
> RUN apt-get update && apt-get install -y pass
> EOF

docker build -t pass .

docker run -it --rm pass bash -c "pass version;pass init;pass init -p foo ABC123"

============================================
= pass: the standard unix password manager =
=                                          =
=                  v1.6.5                  =
=                                          =
=             Jason A. Donenfeld           =
=               [email protected]            =
=                                          =
=      http://www.passwordstore.org/       =
============================================
Usage: pass init [--path=subfolder,-p subfolder] gpg-id...
mkdir: created directory '/root/.password-store'
mkdir: created directory '/root/.password-store/foo'
Password store initialized for ABC123

javabrett avatar Apr 27 '19 05:04 javabrett