Monday, August 24, 2009

Setting up SSH access to Subversion repositories on Solaris 10 (with zones)

If you followed my previous installments, you're probably running some Subversion repositories in your Solaris box. Chances are you're running the Subversion daemon, svnserve, and using the svn protocol to access the repositories: in a previous post I explained how you can set it up as an inetd service and in another post I gave you a pointer to an SMF manifests' repository where you can find a manifest to configure your Subversion daemon with the Solaris SMF framework.

There's another interesting way to access your Subversion repositories: tunneling the communication with svnserve over an encrypted SSH connection.

Why SSH?

There are many reasons that may lead you to such a choice and the most important might be:

  • You're accessing your repositories from outside your network and want to use an encrypted connection.
  • You don't want to maintain (yet another) user registry into the repository configuration files and you'd rather leverage your existing authentication strategy.

With SSH you can have existing users authenticate into your Solaris instances without additional effort. If you're already using some directory service, such as Sun Java System Directory Server, you already know the benefits of centralizing your user registry. If you're not, you should consider using a directory service before starting to duplicate sensible information such as user accounts, groups and privileges. If you're planning to give access to your repositories to users outside your organization, you could think a directory is not a good choice. Well, in this post I'll show you a possible workaround.


To configure such a solution, you have to take into account the characteristics and the consequences of using SSH to authenticate your users into the Solaris Operating System. Whether you're using a directory service or local files (passwd, group, etc.), users who are going to connect must be managed at operating system level. You'll be able to give users access to your repositories without actually allowing them to perform any other operation on your system. Paranoid administrators shouldn't worry about users logging in into their machines, if they don't want to.

Subversion client configuration also allows you to fine tune the tunnel settings: you can change the binding port or the entire command itself, if you wish to.

You will also pay attention to the repositories' permissions: connecting via SSH, under some aspects, is just like using the local file protocol. Users connecting to your repositories, then, should have appropriate permissions on the repositories' directories.

You will also be able to leverage the Solaris Zones technology to isolate your Subversion repositories and users into a non global zone.

Configuring Subversion

This is pretty easy: if you're not fine tuning the tunnel definition, there's really nothing to configure. Just invoke the Subversion client using the svn+ssh schema and the job is done.

If you wished to fine tune your tunnel settings, you can edit the Subversion client config file. This file contains a section named [tunnels]. The config file is located in the .subversion subdirectory into your $HOME. If you want to change the default behavior associated to the svn+ssh schema, just edit (or create if it's missing) a line such as:

ssh = command

To change the default port, you could use:

ssh = ssh -p portnumber

If you wanted, you could also define your own schemas:

yourschema = yourcommand

would be used when accessing the repository with the svn+yourschema schema.

Another nice feauture of the configuration file is the possibility to override the tunnel definition with an environment variable. Defining a schema with the following syntax

yourschema = $YOURVAR yourcommand

has the following effect:

  • If the variable $YOURVAR exists, it's used as the tunnel definition.
  • If the variable doesn't exist, the tunnel definition provided in the configuration file is used instead.

The default value for the SSH tunnel definition is indeed the following:

ssh = $SVN_SSH ssh

When overriding the SSH tunnel definition you may choose to setup the $SVN_SSH variable for your users instead of modyfing the Subversion configuration file. We'll use this technique later.

Setting up the repository

One thing to take into account when using the SSH tunnel is that the svnserve command will be run with your user identity. This means that the user you're logging with must have proper permissions to access the repository files. The easiest way to go is probably creating a group for your users, let's say svn-group, and gave them write access to the repository directory, repository-dir:

$ chgrp -R svn-group repository-dir

$ chmod -R g+w repository-dir

If you're setting up multiple repositories you can create a group for each one of them. Please take into account that the Solaris operating systems allows an user to belong to a maximum of NGROUPS_MAX groups. If you also need to change the current group membership of an user because the required group is a Solaris secondary group, you can wrap the svnserve command into a script which changes the current user's group with the newgrp command.

Another good practice is setting a sane umask before accessing the repository files. You could wrap the svnserve command, or even the svn command if you're using the file schema too, into a shell script which sets the umask for the user:

umask 002
# your commands here

Setting up public keys to use with SSH (and restrict user to only use Subversion)

When opening a SSH session, you're usually asked a password to authenticate into the remote machine. As explained in an earlier post, you can generate key pairs and use them for authentication. Key pairs also have another advantage: you can provide some users a key pair to authenticate and configure the SSH daemon to restrict their abilities to interact with the system. Specifically, you can setup the remote machine to only allow some users to launch a specific command, svnserve in this case, when authenticating. This is especially useful when you share a repository with users outside your organization. You can create user accounts and key pairs for them: with a proper configuration such users, although listed in your user database (both local files or directories such as LDAP), they will only be able to login and launch the svnserve command in tunnel mode. This approach together with Solaris Zone technology will give you the possibility:

  • To quickly set up zones on your system to host subversion repositories.
  • To optionally centralize your user accounts in the directory of your choice.
  • To limit some user account to only use the Subversion server, effectively prohibiting them to open an interactive login session into your system.
  • You can centralize the setup of the users' home directory by using the Solaris automounter. Subversion-only users will have their homes automounted from an ad-hoc server.

To configure the machine, or the Solaris zone, which hosts the Subversion server, you only have to follow the instructions in this post to provide them a key to connect to the server. Once this is done, if you want to limit your user ability by specifying a command to execute at login, you just have to add this fragment before the public part of the key:

command="/opt/csw/bin/svnserve -t"

In this case I specified svnserve path as installed by the Blastwave's package: if your setup is different, just change the path. If you're using Solaris Express Community Edition or OpenSolaris, Subversion may be found in:

command="/usr/bin/svnserve -t"

Please be aware that this fragment must be inserted before the key fragment and in the same line.

If the number of the users is such that you don't want to manage this process manually, you can for example:

  • Use a script to generate the keys and to concatenate the public part into the authorized_keys2 file.
  • Manage a centralized authorized_keys2 file.
  • Share the authorized_keys2 file amongst users' home directories: they won't be able to read that file.
  • Optionally automount users' home directories to share this configuration in many systems or zones.

Configure your users' groups

As mentioned earlier, users should belong to a group with the necessary permissions (read and write) on the repository directory. If you manage your users with local files, just assign them the proper primary and secondary roles: if you need secondary roles for some users you can use the newgrp command in a wrapper shell script to have an user login into the desired group before invoking the Subversion commands.

If you use a directory service, configure the directory appropriately. If you're using the Sun Java System Directory Server and you're using the default LDAP schema, assigning groups to user is pretty easy:

  • The primary group can be specified setting the gidnumber attribute of the LDAP user entry.
  • The secondary groups can be specified by adding multiple memberuid attributes into the group entry.

To add the users joe and john to a group you just add:

memberuid: joe

memberuid: john

into the group definition.

An alternative configuration with just one subversion user

If you do not want to leverage your existing user repository or you don't even have one, don't worry. In that case, all you have to do is setup your subversion repositories as usual and then manually setup the user for the current tunnel with the --tunnel-user=username option in the authorized_keys files. That's it.

Setting up zones

Setting up sparse zones in Solaris 10 is really straightforward and Sun Solaris 10 official Zones documentation covers the topic with great detail.

If you need to configure the zone to use an LDAP, please refer to the Solaris 10 Naming and Directory Services administration guide.

If you want to follow my advice, you can setup a zone for installing Blastwave's software and share the installation between zone using a loopback mount.

Next steps

You can now:

If some of your users run Windows, you can read the following post to learn how to configure TortoiseSVN to use your public key to connect to Subversion using an SSH-tunneled connection.

No comments: