Technical Tip: How to get subversion to remember credentials on a Linux CLI environment in 2022

And now for a bit of a technical aside — my regular readers will probably want to skip this post as it has little to do with regular gamedev news from me.

However, I find myself in the situation of needing to document a technical solution, and having nowhere else to post it, will sneak it into this blog.  Mostly so next time I stumble into this, I can quickly look up the solution instead of re-solving it again and again.  (Yes, I am absolutely the kind of dev who searches for a technical solution, only to find and follow my very own post from a few years prior :P)

((And also because I don’t have enough reputation points to post this answer on Stack Overflow — ironically, too many people there have this question, which has increased the rep required to post an answer… meanwhile all the answers are wrong/outdated, leading more people to have this question….  Ah, classic Stack Overflow, lol))

Background – Subversion

Subversion is a version control system used by some developers to store game assets during development.  Most devs have moved on to using git or perforce, but svn is still used by a few indies (like myself) thanks to its ease of use and binary file handling.  That said, even I have been using git more frequently lately and have been eying the ongoing development of LFS.  Subversion is not without its quirks, and I have had my fair share of subversion corrupting itself randomly.  To be fair, I’ve also seen the very nice, but very expensive Perforce software corrupt itself.  Meanwhile, svn is good and free so… I’m still using svn (with lots of backups and automated checks!  Actually, I should probably document that script sometime, too…)

Background – Plaintext & Machine Credentials

Question:  When is it okay to store plaintext / unchallenged credentials?

For storing a human’s credentials (ie, user databases, etc), basically never.  (In fact, I use strong one-way hashing for this to safeguard passwords securely)

But machine credentials work differently than human credentials.  Basically, servers have automated processes.  A server needs to be able to use its credentials, even when a human isn’t there to type them in. Example: SSL certs on web servers — the web server needs to be able to read the cert’s private key whenever it starts up.  If it can’t, the website won’t start and it’s offline.

Or in today’s case,  a build server that needs to automatically login to a version control software in order to make automated builds for a game.  In that situation, you absolutely wouldn’t want to have to walk over to the build server and retype a password over and over again.  It’s designed to be fire & forget.  Check in code, wait, get builds automatically.

Unfortunately, in recent versions, Subversion makes this quite difficult as the developers have conflated human credentials with machine credentials.

Problem

Due to some crazed moon logic, the subversion developers have decided to make support for plaintext passwords a compile-time option.  While this might make sense for desktop installs that have keyrings, it very much does not make sense for automated build servers and some other CLI environments.  In the aforementioned link, I already commented at length on how astoundingly foolish this decision is, but it’s two years since that post and as svn continues to dwindle ever lower in usage (for this and other reasons), the developers don’t seem to want to budge.  So, assuming you don’t want to recompile + maintain svn from source (and you probably don’t!), now we are firmly in workaround territory.

Workaround #1 – ZSH Script

The ‘compromise’ subversion developers are now instituting is that even if subversion was not compiled with plaintext support, you can still crowbar it in by using an external tool.  Basically, the external tool will write plaintext passwords, and all versions of subversion (even without compiled support for it) will be able to read plaintext passwords.  (I have no idea how they decided that this is somehow better than the old method of just using a run-time override flag  ¯\_(ツ)_/¯  )

This script by Daniel Shahaf was posted in the thread as a workaround:

#!/usr/bin/env -S zsh -f
# Prompt for a realm and a password, then cache that password for that realm, in plaintext.
PS3="Enter the number of the selected option: "
creds=( "${(ps.\n\n.)"$(LC_ALL=C svn auth)"}" )
creds=( ${(M)creds:#-*} )
select m in $creds
do
        realm=${(M)${(f)m}:#Authentication realm: *}
        realm=${realm#*: }
        IFS= read -s -r pw"?Password: "
        md5=${"$(printf %s "$realm" | openssl md5)"##*= }
        print -rC1 \
                \$ i \
                "K 8" passtype "V 6" simple \
                "K 8" password "V ${#pw}" "$pw" \
                "." \
                "w" \
                "q" \
                | ed -s ~/.subversion/auth/svn.simple/$md5
        echo edited $_
        break
done

And this process seems effective for usage:

  1. Do an initial test download from the repo (ie svn co https://user@location/repo dest)
  2. Note that every time you try to update, you get password prompted
  3. Dump the above script into a storePlaintextSvn.zsh file
  4. apt-get install zsh if you don’t already have zsh
  5. Then run zsh storePlaintextSvn.zsh
  6. Select the repo (you’re looking for a ‘svn.simple’ entry)
  7. Enter password
  8. Now re-try the svn update, and it should work without badgering you for a password
  9. Now you can do whatever svn build automation you were working on without manual human intervention.

I tested this on Ubuntu 20.04 and it seems to work so far!

Workaround #2 – Python Script

The FAQ on this very issue also now mentions a Python script forthcoming.  It looks like it will be located here, though as of this writing it’s not actually linked yet.

Share