A journey to find those pieces of software or technology that facilitate productive and maintainable software development

Wednesday, February 25, 2009

Instant Windows SVN Server with SSL and ActiveDirectory

I am not joking. After a significant amount of fiddling and application of Occam's Razor I have come to a configuration of Apache 2.2 that delivers a completely functional and relatively secure SVN server. To be honest it isn't instant, but it is pretty easy to do and will give a robust configuration that should not need post-install tweaking.

Get the pre-requisite software and libraries in place

  1. Download and install the MSI for Apache 2.2 for Windows with OpenSSL
  2. Download the archive of Apache 2.2 Subversion binaries
  3. Extract svn-win32-1.6.3.zip
  4. Copy bin\intl3_svn.dll and bin\libdb44.dll to Apache2.2\bin
  5. Copy bin\mod_authz_svn.so and bin\mod_dav_svn.so to Apache2.2\modules
  6. Download the Apache 2.2 version of mod_auth_sspi
  7. Extract mod_auth_sspi-1.0.4-2.2.2.zip
  8. Copy bin\mod_auth_sspi.so to Apache2.2\modules

Sign Yourself an SSL Certificate (it is better to buy one, but this is cheaper)

Create Apache2.2\createSSLCert.bat with the following content:
bin\openssl req -config conf\openssl.cnf -new -out my-server.csr
bin\openssl genrsa -out conf\privkey.pem 2048
bin\openssl rsa -in conf\privkey.pem -out conf\server.key
bin\openssl req -new -key conf\server.key -out conf\server.csr -config conf\openssl.cnf
bin\openssl x509 -in conf\server.csr -out conf\server.crt -req -signkey conf\server.key -days 4000
bin\openssl x509 -in conf\server.crt -out conf\server.der.crt -outform DER

Carefully fill out the SSL Certificate Details

It is critical that the Common Name on the Certificate match the fully qualified domain name of the server. I found that Apache was unable to use it for SSL otherwise. A mismatched Common Name (CN) also confuses the hell out of client software. Double-click createSSLCert.bat to start the process of building the SSL cert and key. There are a lot of prompts so be patient.

Create new file Apache2.2\conf\extras\httpd-dav-svn.conf:

LoadModule ssl_module modules/mod_ssl.so
LoadModule dav_module         modules/mod_dav.so
LoadModule dav_svn_module     modules/mod_dav_svn.so
LoadModule sspi_auth_module modules/mod_auth_sspi.so
Listen 443
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl
SSLPassPhraseDialog  builtin
SSLSessionCache        shm:logs/ssl_scache(512000)
SSLSessionCacheTimeout  300
SSLMutex default
<VirtualHost _default_:443>
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile conf/server.crt
SSLCertificateKeyFile conf/server.key
<FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "cgi-bin">
    SSLOptions +StdEnvVars
</Directory>
CustomLog logs/ssl_request.log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
<Location />
    DAV svn
    SVNListParentPath on
    SVNParentPath C:/Repositories
    AuthType SSPI
    SSPIAuth On
    SSPIAuthoritative On
    SSPIOfferBasic On
    SSPIBasicPreferred On
#    SSPIDomain DEVDOMAIN (Optional)
    Require valid-user
</Location>
</VirtualHost>
Add to end of Apache2.2\conf\httpd.conf:
Include conf/extra/httpd-dav-svn.conf

IMPORTANT: Restart the server (use shutdown -r -t 3 from the Command Prompt if you are using RDP)
You need to restart because otherwise the modules will not load correctly. I am not exactly sure why, but I tried this several times without restarting and it failed every time. This is not superstition it is actually required.

Add a new repository to your server

  1. Add svn-win32-1.6.3\bin to your System Path
  2. Run svnadmin create C:\Repositories\svn

One particularly nice thing is that you can add any number of repositories without having to dig into Apache's config and without restarting Apache.

Take a look at https://localhost/ with your web browser. You should now have a functional Subversion server authenticating against your ActiveDirectory Domain listing svn as a repository. Enjoy :)

Tested Working Clients

  • svn command line on Windows
  • Internet Explorer 6 on Windows
  • Chrome on Windows
  • Firefox on Windows
  • svn command line on Mac OS X
  • Subversive in Eclipse on Mac OS X
  • WebKit on Mac OS X

Oddly enough Internet Explorer actually chokes if SSPIBasicPreferred is not on. In theory it should successfully authenticate with NTLM in the single sign-on style, but it hangs or gets rejected by the server instead. We are using SSL anyway so HTTP Basic is reasonably safe.

23 comments:

Unknown said...

I believe there is a typo in the http-dav-svn.conf file listing.

You have:

[Location /]
DAV svn
SVNListParentPath on
SVNParentPath C:/Repositories
AuthType SSPI
SSPIAuth On
SSPIAuthoritative On
SSPIOfferBasic On
SSPIBasicPreferred On
# SSPIDomain DEVDOMAIN (Optional)
Require valid-user
[/Location]

Should be:

[Location]
DAV svn
SVNListParentPath on
SVNParentPath C:/Repositories
AuthType SSPI
SSPIAuth On
SSPIAuthoritative On
SSPIOfferBasic On
SSPIBasicPreferred On
# SSPIDomain DEVDOMAIN (Optional)
Require valid-user
[/Location]

Notice the closed tag on [Location].

-bill

Bill said...

Alan:
I got LDAP working, but am interested in SSPI for many of the reasons you cite, so will look into it. Thanks.

One thing I don't see covered in most of these articles (SSPI or LDAP) is, once you get Apache working properly with SVN, what do you need to do in terms of SVN access controls to properly control access to repositories? How does this stuff present to SVN in terms of built-in or SASL security? What's needed is a more complete example that includes some discussion of SVN security in light of SSPI.

Thanks!

Bill said...

(Make that Alain - sorry...)

Unknown said...

@William:

Interesting. I did not realize that you could omit the path for the root Location. Thanks :)

Unknown said...

@Bill:

Sorry for the late reply. I have not successfully implemented role-based access controls, but it is possible. It is my understanding that multiple <Location> directives can be used so that different parts of the SVN repository or repositories are made accessible to different users. You can also use <LimitExcept> and <Limit> directives within a Location to grant a subset of privileges like read-only access. A combination of these allows you to configure things such as module committers and authorized client teams of modules.

Anonymous said...

I'm hoping to use this guide to segment out an SVN repository amongst multiple users. I have some domain-local Active Directory LDAP groups I want to set access by.

To be clear, I could use this example and then add the "LimitExcept" directive, and specify which groups are allowed access?

How then do I differentiate between read privileges and read/write?

Anonymous said...

Ah, I already see I was confused - I'd be limiting SVN methods, such as "GET PROPFIND OPTIONS REPORT". I think I will try blending your method with this guide:

http://www.jejik.com/articles/2007/06/apache_and_subversion_authentication_with_microsoft_active_directory/

Unknown said...

Hi,

I have followed the how to , but when i try to access https://localhost it gives me an error saying it cant establish a connection also the my two apache services, only one of them will start, and thats the Collabnet one, not the apache service, any ideas?

Unknown said...

@Lynda:

Uninstall the CollabNet one :)

I had the same problem. They conflict...

Unknown said...

Hi Alain,

I was hoping it would be okay with you if I linked to this post from my site. We have a web-based Subversion Management application designed for Windows environments called Sublime. Today Sublime won't configure Apache automatically (although we hope to offer that in the future) so having reference information like this for our customers is important.

Regards,
Glen Cooper
Sublime - Easy Subversion Management for Windows
http://sublimesvn.com

Unknown said...

@ ALain -thanks for getting abck to me.

After putting in the line to Include conf/extra/httpd-dav-svn.conf i get the below


module dav_module is already loaded, skipping
httpd.exe: Syntax error on line 482 of C:/Program Files/Apache Software Foundati
on/Apache2.2/conf/httpd.conf: Syntax error on line 3 of C:/Program Files/Apache
Software Foundation/Apache2.2/conf/extra/httpd-dav-svn.conf: Cannot load C:/Prog
ram Files/Apache Software Foundation/Apache2.2/modules/mod_dav_svn.so into serve
r: The specified procedure could not be found.
Note the errors or messages above, and press the ESC key to exit. 22...

Ranga said...

Alaine,

True to your blogs mantra, this is indeed an awesomely concise article :)

I did run into one problem though - the whole setup works fine if I access SVN via a browser from the same machine on which Apache & SVN are installed, but I cannot access from the any other machine on the network! I checked the DNS entries & they carry the proper mappings for the Apache/SVN server machine. I also imported the server certificate into the browser on another machine. Additionally I added the IP/machine name info (redundantly) into the hosts file. Still no luck!

Was curious if you have come across something like this. Quiet a bummer for now :(

Unknown said...

I have this line in config/http.conf

#LoadModule dav_module modules/mod_dav.so

and as you wrote in article in this file: conf/extra/httpd-dav-svn.conf
I have
LoadModule dav_module modules/mod_dav.so

(notice its not commented out )

And I am getting error (almost same as Lynda's):

Cannot find and load the module to server.
But I have the module on the sever. Why is this happening?

Gilles Duchesne said...

Alas,I have to say that I'm in the same situation as Lynda: I'm being told that mod_dav_svn.so cannot be loaded, no matter what.
* I triple-checked that I had the right paths, even loading a different module just to make sure.
* You had mentioned a need to reboot, so I did, time & again.
* On other forums, I read that this error could mean that the process wasn't able to access the file, so I checked users rights, ensured that parents' rights were applied to my copied files. Still no change.

I still suspect my files might somehow be out of reach of the Apache process, but at this point in time I have no clue what the specific problem could be... :-(

Unknown said...

@Lynda, @How to Make Millions..., @Gilles Duchesne:

Unfortunately the only way I could get Apache httpd to see the modules was to restart the machine.

If you have and the modules and still not found then I am stumped. If so, post back your config.

Unknown said...

@Ranga:

Try running a default Apache httpd configuration from a fresh install and attempt to connect to http://thehostip/. You should get a page that says:
It Worked!

If not, then there may be a cornucopia of other firewall/router issues which I have no expertise in resolving.

//. said...

I just spent some four hours following this very concise tutorial. Here are the caveats:

1. @William: the slash after Location tag is the root URL of the svn repository. I didn't quite appreciate the Alain's wonderful understatement in his reply until I tried removing it.

2. The directive SVNParentPath does not point to the repository itself but one level up (i.e. to a folder that can contain several repositories). Note that in Alain's example, the SVNParentPath is C:/Repositories, while the repository he creates is C:/Repositories/svn

3. I was confused about mod_authz_svn or lack of it. Finally I realized that in this setup, everybody has rights to everything, the point is that all changes are traceable to the person who made them.

Anyway, now it works, many thanks Alain.

Unknown said...

@//.:

My pleasure. I'm glad that my guide worked for you :)

Jack Repenning said...

Hello,

According to our monitoring, this blog is a very popular referral point for people who want to download Subversion.

We thought you would like to know that the Subversion download area has been reorganized. Your links to subversion.tigris.org do not work any longer. This is because the binary versions to which you link are no longer supported or maintained.

You might want to change your links to point to one of the active downloads, such as the CollabNet Subversion distribution:

http://www.open.collab.net/downloads/subversion/

Unknown said...

Hello, I am trying your tutorial and see that the link does not work for "2. Download the archive of Apache 2.2 Subversion binaries". Do you know where I can get the files for the bin? Thank you.

Unknown said...

@Andres: I've updated the howto to use the Subversion 1.6.3 binaries.

Seriously though if you have the option now, dodge the Subversion bullet and use Git. It is better than Subversion at everything.

Subversion's merging and distribution limitations discourage good branching practices by making them hard to do right.

VC said...

Appreciate if some one can help me with this?

1) Just wondering on the rationale for using Apache here in place of IIS ?
2) Also if StatSVN and svnstats can be got to work if IIS is used in place Apache in this article, though substituing the for equvialent steps for Active Directory configuration.

Thanks

VC

Unknown said...

@VC:

The primary reason I chose Apache httpd for this is that the Subversion book provides instructions for that.

I wasn't aware that Subversion could be configured to run in IIS. Please post back when you get that running. It sounds like a cleaner option: less patch maintenance :)

Cheers,
Alain

SyntaxHighlighter