The lastpass command line client

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

  1. wrapper script
  2. mutt integration
  3. msmtp integration
  4. ssh-agent integration
  5. gpg-agent integration

The lpass wrapper script: lpass-wrapper.sh

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.

Integrating LastPass with mutt

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.

Integrating LastPass with msmtp

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.

Integrating LastPass with ssh-agent

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.

Integrating LastPass with gpg-agent

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