Scripting sudo with pass

Like a lot of folks, I use zx2c4's pass. Like even more people, I use sudo for administrative tasks on my machines.

Seamless integration

A lot of tools (offlineimap, docker, ansible-vault...) offer a way to provide the password through an external command. This is where pass excels. By allowing you to extract any password with a simple command line, it lets you have all of your passwords in one place, with no overhead in your workflow.

What about sudo?

If you want to run a sudo command without typing the password interactively, you would normally use the NOPASSWD option in /etc/sudoers. I do not find it desirable: should you leave a console unattended, this exposes you to somebody running administrative commands too easily.

So can you instead tell sudo to use pass for the password input? Sort of. The -A command line option is designed to provide the password through an helper program. To quote the manpage:

If the -A (askpass) option is specified, a (possibly graphical) helper program is executed to read the user's password and output the password to the standard output. If the SUDO_ASKPASS environment variable is set, it specifies the path to the helper program.

Let's take advantage of this!

Implementation

I store in pass my different "user@host" passwords under the path host/<user>@<host>. If you adopt the same convention, this is what you can do:

Save the following file as executable under ~/.local/bin/sudo-askpass

#!/bin/bash
pass show hosts/$(whoami)@$(hostname) | head -n1

Insert your password in pass accordingly

pass edit hosts/$(whoami)@$(hostname)

And now if you run

export SUDO_ASKPASS=$HOME/.local/bin/sudo-askpass
sudo -A whoami

The answer should be root. Neat, but not seamless, since you need the -A switch. You could solve the problem by adding these 2 lines in your shell startup file

export SUDO_ASKPASS=$HOME/.local/bin/sudo-askpass
alias sudo='sudo -A'

However, programs which invoke sudo (such as yay) will not know about this alias, and you will still be required to type your password interactively. What I do instead is to create my own sudo executable with higher precedence in the path whicht insert the proper options before invoking the real binary:

#!/bin/bash

SCRIPTDIR=$(dirname $(which $0))
PATH_WITHOUT_SCRIPTDIR=$(echo $PATH | tr ":" "\n" | grep -v "$SCRIPTDIR" | tr "\n" ":")
REAL_SUDO=$(env PATH=$PATH_WITHOUT_SCRIPTDIR which sudo)
exec env SUDO_ASKPASS=$HOME/.local/bin/sudo-askpass $REAL_SUDO --askpass "$@"

If your distribution follows the systemd file hierarchy, you can save this file under ~/.local/bin/sudo and it will happily take precedence over the real sudo.

Keychain

I employ a similar trick for unlocking my ssh keys with keychain. I store in pass the password of the private ssh key of <user>@<host> as ssh/<user>@<host>. The following file is saved as executable under ~/.local/bin/ssh-askpass

#!/bin/bash
pass show ssh/$(whoami)@$(hostname) | head -n1

And this goes in my shell startup file

{type keychain > /dev/null} && {type ssh-askpass > /dev/null} && \
    source <(SSH_ASKPASS=ssh-askpass keychain --quiet --eval id_rsa </dev/null)

More to come

If you have a look at my dotfiles, you will realize that there is more to this setup. The main additional thing to know is that I use a smartcard to handle the gpg decryption, so that no machine contains the gpg key that I use with pass. This will likely be the purpose of a different article. Until then and as always, I am gladly taking any comment.

Happy sudo-ing!

To the comments

All posts

  1. Looping simultaneously over multiple lists in legacy shells
  2. SSH over SSL, episode 4: a HAproxy based configuration
  3. Editing a CV in markdown with pandoc
  4. Using openid and the likes to protect static content (lighttpd)
  5. Git on lighttpd
  6. Sigal, a static gallery generator
  7. Jabber notifications on ssh login
  8. Choose your passphrase with a die
  9. Operations Research and Beer drinking
  10. Releasing Michel, a flat-text-file-to-google-tasks uploader
  11. Going static
  12. plowbot, a jabber bot that downloads links from 1-click hosters
  13. SSH over SSL, episode 3: Avoiding using a patched apache.
  14. [Je préfère ton clone] padopi
  15. Using a shell version of supergenpass from vimperator/pentadactyl
  16. Saving your crontab in your dotfiles
  17. Notifications from google calendar on my desktop
  18. SSH over SSL, episode 2: replacing proxytunnel with socat
  19. SSH over SSL, a quick and minimal config.
  20. Vim: complete C++ accurately, pulling informations from the compiler, with gccsense and clang_complete
  21. Google releasing a constraint programming library
  22. Mise à jour de TalkMyPhone
  23. TalkMyPhone, une appli android pour recevoir des notifications de son téléphone
  24. De l'intérêt de détacher des programmes de la console (sans screen)
  25. renaming files and variables from vim
  26. Continuous background compilation within vim
  27. Utilisons incron pour être notifiés des événements du système de fichiers
  28. La TODO liste du pauvre
  29. Gérer ses plugins vim avec :GetLatestVimScripts
  30. gdb 7.0 est sorti, c'est une merveille et vous ne le saviez pas.
  31. autotools, doxygen, et génération conditionnelle
  32. Mettre des couleurs un peu partout (gcc, diff, grep...)
  33. vim+gdb=vimgdb
  34. l'UML automatisé et le libre : c'est pas gagné!
  35. Les lecteurs de flux rss, en ligne, indépendants, libres (suite).
  36. Les lecteurs de flux rss en ligne libres
  37. Couper une vidéo et extraire une scène d'un film
  38. Faire un gif animé à partir d'un film

Atom feed