subversion via ssh passphrase-less key

In general, passphrase-less ssh keys are a security nightmare. It is similar to leaving the key to your front door in the lock. Anyone stumbling across it has access to your house.

Similarly, if someone gets your ssh key, and there is no passphrase on it, they can use that key for anything which grants access to that key.

Side note: How can you tell if a given ssh key has a passphrase?

  1. Try ssh-add on that key. If you get prompted for a passphrase, there’s your answer.
  2. Look at the private key. If you see the word ENCRYPTED in an RSA key, it is passphrased.

Are there other ways? I don’t know. I can’t see anything in an ed25519 which tells me.

In this post, I will show you how I secured the use of a passphrase-less ssh key for use on a subversion repository.

This post does not show you up to set up a subversion repo; that is outside scope.

This post deals with FreeBSD 11, FreeBSD 10.3, and subversion 1.9.7, but should apply widely to many operating systems and versions.

My use case

I will outline my particular use case in case what I’m doing prompts you to discover something that you have always wanted to do, but didn’t know how.

I’ve started using dynamic DNS updates as part of my centralized Let’s Encrypt solution. This solution certificates for multiple domains and distributes those certificates via a website. Keys are managed out of band and manually.

Somehow, I stumbled across Jan-Piet Mens’ post about nsnotifyd, created by Tony Finch. I was impressed. nsnotifyd can be thought of as a teeny weeny DNS server with limited functionality. It listens for a DNS NOTIFY, then invokes a script. That’s it.

The beauty of it is that script can do anything. Anything.

One of Jan-Piet’s suggested uses for nsnotifyd was backups. This immediately appealed to me. I wanted to use this tool to backup my zones files as each change occurred. Some might ask why. It might help to know that I have stored my zone files in a repository since at least 2002. I would update my working copy, commit, and then distribute to my servers.

I like the concept of storing the zone files in a repository. Now, I can use this as my backup method. Yes, I’ll still backup that repo, but I like the audit trail.

I can also use nsnotifyd for monitoring. A new zone file has just been published? Do all the master DNS servers have the new SOA values? Yep, all good.

Creating the ssh key

I created the new ssh key on the same server as which nsnotifyd was already running.

ssh-keygen -t ed25519 -f ~/.ssh/public-dns-updates

Pick whatever file name you prefer. You will be particularly interested in the .pub file which the above creates.

Adding the key to the subversion server

On the subversion server, I altered ~/.ssh/authorized keys to contain this entry:

command="/usr/local/bin/svnserve -r /usr/local/svn/repos/dns -t --tunnel-user=dns-notify",from="10.0.0.245",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOqgPwv2KO+8MrbAx1u4bvnO+VVgbxSe+IQjxJQslyNO dan@mydev.example.org

The main components of this directive are:

  1. command – This is the command invoked when the ssh connection is invoked.
  2. svnservea lightweight server, capable of speaking to clients over TCP/IP using a custom, stateful protocol. Clients contact an svnserve server by using URLs that begin with the svn:// or svn+ssh:// scheme.
  3. -r /usr/local/svn/repos/dns – restricts usage to only repositories below that path
  4. -t – specifies the tunnel mode & invokes a private svnserve process as that user which is logged in via ssh
  5. –tunnel-user=dns-notify – tells svnserve to assume that the named argument is the authenticated user. Commits will appear to be done by this user.
  6. from – incoming ssh connections will only be accepted from the specified IP address.
  7. no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty – This imposes various restrictions upon the incoming ssh connection and tightens things down.
  8. ssh-ed25519 … – The contents of the .pub file created via ssh-keygen in a previous step. This is the ssh public key.

subversion working copy changes

The -r parameter above changes things for your subversion client. If you already have a working copy checked out and you try to check in, it will fail. Perhaps like this:

$ svn ci -m 'testing new ssh key'
Sending        unixathome.net.db
Sending        unixathome.org.db
Transmitting file data ..done
Committing transaction...
svn: E160013: Commit failed (details follow):
svn: E160013: File not found: transaction '4215-39o', path '/usr/local/svn/repos/dns/branches/NO_TSIG_BRANCH/unixathome.net.db'
Killed by signal 15.

I will get back to that signal 15 later.

This was my original svn info:

$ svn info
Path: .
Working Copy Root Path: /usr/home/dan/dns-public-BRANCH
URL: svn+ssh://dan@svn.example.org/usr/local/svn/repos/dns/branches/NO_TSIG_BRANCH
Relative URL: ^/branches/NO_TSIG_BRANCH
Repository Root: svn+ssh://dan@svn.example.org/usr/local/svn/repos/dns
Repository UUID: e9903129-21d8-e211-989e-002590a4cdd4
Revision: 4211
Node Kind: directory
Schedule: normal
Last Changed Author: dan
Last Changed Rev: 4192
Last Changed Date: 2017-07-11 22:08:30 +0000 (Tue, 11 Jul 2017)

I originally thought svn switch was what I wanted, but no, it was svn relocate:

$ svn relocate svn+ssh://dan@svn.int.unixathome.org/dns/branches/NO_TSIG_BRANCH
Killed by signal 15.

That Killed by signal 15 message made me think it had failed, but svn info showed otherwise:

$ svn info
Path: .
Working Copy Root Path: /usr/home/dan/dns-public-BRANCH
URL: svn+ssh://dan@svn.example.org/dns/branches/NO_TSIG_BRANCH
Relative URL: ^/branches/NO_TSIG_BRANCH
Repository Root: svn+ssh://dan@svn.example.org
Repository UUID: e9903129-21d8-e211-989e-002590a4cdd4
Revision: 4211
Node Kind: directory
Schedule: normal
Last Changed Author: dan
Last Changed Rev: 4192
Last Changed Date: 2017-07-11 22:08:30 +0000 (Tue, 11 Jul 2017)

Now my commit works:

$ svn ci -m 'testing new switch'
Sending        unixathome.net.db
Sending        unixathome.org.db
Transmitting file data ..done
Committing transaction...
Committed revision 4216.
Killed by signal 15.

Killed by signal 15

I was concerned by that, but a search found that the message is generated by ssh.

Adding the -q parameter to ssh will fix that. More on this parameter later.

The commit script

The following is the script which nsnotifyd invokes for me. I maintain it in GitHub.

$ cat ~/bin/dns-notify
#!/bin/sh

MYNAME="dns-notify"

ZONE=$1
SERIAL=$2
MASTER=$3

SVN_SSH="/usr/bin/ssh -qi /usr/home/dan/.ssh/mydev-public-dns-updates"
export SVN_SSH

DIG="/usr/local/bin/dig"
LOGGER="/usr/bin/logger"
SVN="/usr/local/bin/svn"
ZONE_FILE_DIR="/usr/home/dan/dns-public-BRANCH"

${LOGGER} -t ${MYNAME} has been invoked with zone=\'$ZONE\', serial=\'$SERIAL\', and master=\'$MASTER\'.

cd ${ZONE_FILE_DIR}
${DIG} +noall +answer +onesoa +rrcomments @${MASTER} ${ZONE} axfr > ${ZONE}.db
${SVN} ci -m "serial ${SERIAL}" ${ZONE}.db

${LOGGER} -t ${MYNAME} $ZONE with serial ${SERIAL} has been saved.

Some notes on the above:

  1. Lines 6-8 grab the incoming parameters from nsnotifyd.
  2. Line 10 includes that -q parameter previously mentioned, and specifies the passphrase-less ssh key.
  3. Line 21 pulls the zone file from the DNS server.
  4. Line 22 does the commit

That’s it. Done.

Log messages

The following are the log messages I get when this script runs:

Aug 19 21:11:32 mydev dns-notify: has been invoked with zone='unixathome.net', serial='2014122904', and master='10.0.0.53'.
Aug 19 21:11:33 mydev dns-notify: unixathome.net with serial 2014122904 has been saved.
Aug 19 21:40:33 mydev dns-notify: has been invoked with zone='unixathome.org', serial='2017053067', and master='10.0.0.53'.
Aug 19 21:40:35 mydev dns-notify: unixathome.org with serial 2017053067 has been saved.
Aug 19 21:42:59 mydev dns-notify: has been invoked with zone='unixathome.org', serial='2017053068', and master='10.0.0.53'.
Aug 19 21:43:01 mydev dns-notify: unixathome.org with serial 2017053068 has been saved.

Time will tell how well this works, but so far, so good. I hope you found what you were looking for.

Website Pin Facebook Twitter Myspace Friendfeed Technorati del.icio.us Digg Google StumbleUpon Premium Responsive

Leave a Comment

Scroll to Top