Automating bzr over ssh without passwords

Thursday, March 3rd, 2011

Well this job took me far far longer than should have been necessary. I wanted to automate the job of updating a bzr branch from a remote server, and the bzr+ssh:// method involved the least change to authentication at the far end.

What I thought was a slight complication was that I need to use an identity file to connect, not a password; and because this is going to come from a script invoked from cron I don’t have a specific user in mind, and no $HOME.

Unfortunately all the examples I can find for bzr talk about changing configs in $HOME, either for bzr itself or for ssh. And only for managing passwords; for keys the only comment was to use an SSH key agent, which isn’t ideal for me. That’s odd, I thought, well I’ll just have to specify things on the command-line, like we can with rsync & friends.

Well, no. There is no space in bzr for specifying options to the underlying ssh (which by default is paramiko). If you look hard in the documentation you might discover the BZR_SSH environment variable though … so perhaps you can set that to point to your own pre-loader script?

Again, no. You can only set BZR_SSH to a pre-defined set of words, and you cannot specify a specific command.

So the only working option that I could find was the nasty nasty method of creating a replacement command called ’ssh’, and to run bzr with this script at the front of PATH. Make sure that you don’t accidentally invoke the real ssh as just “ssh” within that script — use absolute filenames to prevent a forkbombing of your own machine.

This replacement ssh sets the correct username and identity file for the onward connection, and then does just whatever bzr wanted anyway. In order to invoke bzr correctly you need to specify a new PATH and the BZR_SSH setting …

The fake ssh script :-

#!/bin/sh
/usr/bin/ssh -l username \
    -i /full/path/to/identity_file \
    -o IdentitiesOnly=yes $*

The bzr invocation :-

PATH=/full/path/to/fake BZR_SSH=ssh \
    /usr/bin/bzr pull bzr+ssh://remote.host/repo