The folks at LastPass have had the good idea to release an open source command line client called lpass. With this tool we can easily query LastPass from the command line and even script around it.
This guide documents how I used lpass to have various application automatically query LastPass to retrieve password information when needed. All password transfers will be done trough pipes, they won't touch the disk
Once lpass is correctly installed (see the instructions in the github repository) you can log into your LastPass acount using:
lpass login $username
Once successfully authenticated lpass will spawn an agent in the background in order to be able to issue subsequent commands without having to re-enter your master key every time. By default this agent will quit after an hour (see the documentation if you want to modify this behaviour).
This means that you'll have to relog regularly when your lpass agent expires. It would be convenient if we could get lpass to restart the login sequence automatically when you query a password while logged out. We can achieve this with this small wrapper:
#!/bin/sh # lpass-wrapper.sh username='$username' status=$(lpass status) if [ $? -ne 0 ] then if [ "$status" = 'Not logged in.' ] then # Make sure DISPLAY is set DISPLAY=${DISPLAY:-:0} lpass login "$username" 1>&2 else echo "Lastpass error: $status" 1>&2 exit 1 fi fi lpass $@
You'll just have to replace $username
with your
LastPass username. Also make sure that your lpass binary is
somewhere in your $PATH
(or modify the script to
tell it where to find it).
I set DISPLAY
to :0
if it's unset,
this way the script should be able to display the password
prompt dialog even if it's called from an application which
doesn't have the X environment set. This can happen for instance
if it's called from an agent that's started from outside the
graphical environment. It's a bit hacky but it works well in
practice.
With this script in your $PATH
you can try
something like:
lpass-wrapper.sh ls
If you're not currently logged into the service you should get
prompted for your master key. Then the wrapper will
run lpass ls
normally.
We can now use this wrapper to integrate LastPass in other applications.
My email client (MUA) is mutt. Mutt supports invoking an external program to retrieve passwords, you just have to surround the command with backticks (`). For instance:
For instance since I connect to my mail server using IMAP I have
this in my ~/.muttrc
:
set imap_pass = `lpass-wrapper.sh show --password $id`
Where $id
should be the id of the password entry in
your LastPass database (use lpass ls
to list all
entries with their corresponding ids).
With this configuration mutt will call lastpass-wrapper when it
needs the IMAP password, which in turn will call lpass
login
if you're not currently logged in.
I use msmtp to send
my email. Like mutt it supports invoking an external application
to get the password through the passwordeval
directive.
For instance in my ~/.msmtprc
I use:
passwordeval lpass-wrapper.sh show --password $id
Where $id
is the id of your SMTP password entry in
the LastPass database.
Now things get a bit messier, because ssh-add has to be coherced into accepting to use an external application to get a password and you can't even pass custom arguments.
Since we won't be able to pass command line arguments to our
wrapper script I'm going to use an other script which will
accept the password id through the environment. I call
it lpass-env.sh
:
#!/bin/sh # lpass-env.sh lpass-wrapper.sh show --password $LPASS_ID
Pretty straightforward, you just pass the id in
the LPASS_ID
environment variable.
Now we can use the SSH_ASKPASS
environment variable
to tell ssh-add
to use our script, however it will
only do so if DISPLAY
is not set and its
standard input is not from a terminal.
The end result is this script around ssh-add
which
I call lpass-ssh-add.sh
(we're at 3 levels of
scripts if you're keeping score):
#!/bin/sh # lpass-ssh-add.sh export DISPLAY= export SSH_ASKPASS=/$path_to/lpass-env.sh export LPASS_ID=$id ssh-add $@ < /dev/null
You'll have to replace $id
with the id of your SSH
key password in your LastPass database as well as setting the
correct path to your lpass-env.sh
script.
Now instead of calling ssh-add
you can
call lpath-ssh-add.sh
and it will query lpass
automatically.
If you have several keys with different passwords you'll have to modify the script to handle that but I'm sure you get the general idea.
gpg-agent can be instructed to use a custom pinentry command to retrieve passwords. However unlike other applications this command should not simply spew the password on stdout, rather you have to implement the pinentry protocol.
The way it works is that you receive commands on stdin and reply on stdout. Here's what it looks like:
#!/bin/sh # lpass-gpg-pinentry.sh echo OK while read cmd do case $cmd in GETPIN*) pass=$(~/bin/lpass-wrapper.sh show --password $id) echo "D $pass" echo OK ;; BYE*) echo OK exit 0 ;; *) echo OK ;; esac done
You'll have to replace $id
with the id of your GPG
key password in your LastPass database.
If you have several keys with different passwords you'll have to
be a bit more clever than that. You can probably extract the key
ID from the SETDESC
pinentry directive and use that
to lookup the correct entry in your database.
Finally you can tell gpg-agent to use our pinentry script by
adding this line to ~/.gnupg/gpg-agent.conf
:
pinentry-program /path/to/lpass-gpg-pinentry.sh