Wickedness And Perversion in Subversion
Oh the woe. The last week and a half or so has led to some interesting Subversion related discoveries, mostly shortcomings, defects, or lack of functionality. The follow is a solution focused rant about what went wrong and how I fixed it. Let the world learn from the mistakes of the past.
First off, I have to say that I really like Subversion (SVN). It is a huge step up from CVS, which was my first introduction to versioning software. With atomic checkins (all or nothing) and a simplified database storage method (well it's a DB by default), the file based CVS heap of revision numbers is left in the dust. Since commits are atomic, each commit can be assigned a single revision number, rather than each file having a separate version number based on the number of times it has been committed.
There are also some snazzy authentication methods, something that took a pretty sizable battle to do securely in CVS. The most notable of these is Apache integration using the dav_mod module. This allows repositories to be locked down via HTTP Authentication over SSL (HTTPS), while providing a secure web-based repository browser built right in! I was really loving life using Subversion, but as always, the technology gods find something to get angry over, and soon begin raining down the chaos. Whether it is my wanton disregard of DRM or the demeaning glare of my hacker goggles I will never know, but at any rate, I was bound to eventually uncover some issues, and alas, such was the case.
As many of you are aware, I lack nothing more than my thesis to complete my MS (which has been the case for the past year and a half). Well after ditching my first topic quite a ways in, I have finally settled on the one that will carry me accross the finish line. Sponsored by Doba, it involves the development of a web-based code deployment system to deploy development code to all the various servers it needs to be on to pass through a healthy deployment process. The core of this project involves some fairly intimate interaction with our repository software Subversion. As such, I have been working on that piece of the puzzle recently: trying to access SVN commands through a php script. Urban legend has it that there are some modules written to interact with the SVN client directly for PHP, but they are certainly still in the mythical stage at this point and definitely nto suited for mission-critical use. So, my only alternative was to encapsulate some direct system calls to the SVN client with a PHP object in order to utilize its functionality.
Anyways, on to the problems at hand. Below is a list of some of the "wickedness" I have encountered of late in trying to utilize SVN, along with the eventual solutions:
Externally Linked Folder Woes
So, since we utilize a fairly significant amount of base code, whose breadth spans multiple projects across the site, it is natural to want any changes to that code to be replicated accross its many locations. That in mind, its sort of a pain to have to make changes in several places to accomplish that. Therefore, one of the best solutions is to create externally linked folders in SVN. This allows the code to be stored in a single location, but included as part of various repository folders.
In comes trouble. This apparently has a few hiccups, at least in my version of SVN (which by the way I'm forced to get through redhat, so it is a bit outdated from the most recent version). It was noticed, that in order for the working copy to recognize these new externally linked folders, you have to make it jump through a few hoops and do a little dance. First of all, the root folder of the project (in most cases the 'trunk' folder) has to be updated. Well I didn't want to update everything inside it as well, so I was forced to use the -N flag to make it non-recursive. This alone did not do the trick however. I also had to actually copy the new folders into the path in the working copy. Once I did that I was able to call svn update on the linked folders and they appeared in the SVN versioning as if they had always been there. Not sure why that was the case, but I'm told that is fixed in later versions.
Certificate Hostname Mismatch Woes
This is one of the stupidest issues I have encountered as of yet in SVN. As part of my automated deployment tool, I must execute subversion commands from a web script, which runs as the apache user. For security reasons, this user does not have any home folder, shell functionality, or other resources that conventional users do. Subversion commands however, will present an accept dialog for any less than perfect security problems they encounter, which since the web user has no shell functionality, it is impossible to connect as them and permanently accept the certificate.
Here comes the really stupid part. There used to be command flag in the earlier subversion clients that allowed you to ignore certificate warnings and accept them automatically, but it was removed because it was deemed obsolete! Idiotic decision. That means that either the certificate must be perfect (in this case it was self-signed and I was originally getting a warning because the hostname did not match, and because the CA was not trusted), or you must add the CA cert to the list of approved CA's for all clients on the server if you are going to connect through a web script. Not very friendly towards dynamically allowing the addition of new SVN servers.
So to solve this problem, I finally just had to create a new certificate with the proper hostname to solve the hostname warning, and then add the certificate's .crt file to the server hosting the web script, so that it's SVN client would ignore the CA warning error. I won't go through how to create a new certificate, since there are lots of good sites on that (try http://slacksite.com/apache/certificate.html), but I will tell you how to add the .crt file to the list of approved CA's.
To rid yourself of an invalid CA certificate error. on the SVN client server, go to /etc/subversion as root (if the folder does not exist, jsuts create it - I spent a while figuring out you could do that even with older versions of SVN). Copy the .crt file that was used to sign the offending certificate into this folder. Make sure the certificate file is world readable. Now create a file called 'servers' in the same folder (/etc/subversion), or edit the one that is already there. For added security, we only want to accept the CA for the URL of the SVN repository. So, to the 'servers' file, make the following addition (where 'mygroupname' is a name you have chosen for the group, 'host.domain' is the hostname of the server hosting the SVN repository, and 'host.domain.crt' is the name of the certificate file that you copied over):
[groups]
mygroupname = host.domain
[mygroupname]
ssl-authority-files=/etc/subversion/host.domain.crt
Now, when you connect to the repository on the specified server you should no longer get either of those certificate error warnings.
Subversion HTTP Passwords Stored in Plaintext
The final piece of subversion perversion that I want to share has to do with the fact that HTTP passwords used to connect to an SSL encrypted repository URL, are stored in plaintext on the client machine! Amazing! I know that HTTP authentication is passed in plaintext, but why would anyone use that without tunnelling it through SSL! That's even how it is recommended in the SVN documentation! So, what I don't understand, is why the client wasn't written to encrypt, or at least hash those passwords when caching them on the client. If you want to taste of what I am talking about, connect your SVN client to an HTTP or HTTPS repository location, and then check out '/home/username/.subversion/auth/svn.simple'. Do a 'cat' on one of the files in that folder and you will see the username and password plainly shown! I'm sorry, but that just amazes me as to why people still do that in this day and age!
First off, I have to say that I really like Subversion (SVN). It is a huge step up from CVS, which was my first introduction to versioning software. With atomic checkins (all or nothing) and a simplified database storage method (well it's a DB by default), the file based CVS heap of revision numbers is left in the dust. Since commits are atomic, each commit can be assigned a single revision number, rather than each file having a separate version number based on the number of times it has been committed.
There are also some snazzy authentication methods, something that took a pretty sizable battle to do securely in CVS. The most notable of these is Apache integration using the dav_mod module. This allows repositories to be locked down via HTTP Authentication over SSL (HTTPS), while providing a secure web-based repository browser built right in! I was really loving life using Subversion, but as always, the technology gods find something to get angry over, and soon begin raining down the chaos. Whether it is my wanton disregard of DRM or the demeaning glare of my hacker goggles I will never know, but at any rate, I was bound to eventually uncover some issues, and alas, such was the case.
As many of you are aware, I lack nothing more than my thesis to complete my MS (which has been the case for the past year and a half). Well after ditching my first topic quite a ways in, I have finally settled on the one that will carry me accross the finish line. Sponsored by Doba, it involves the development of a web-based code deployment system to deploy development code to all the various servers it needs to be on to pass through a healthy deployment process. The core of this project involves some fairly intimate interaction with our repository software Subversion. As such, I have been working on that piece of the puzzle recently: trying to access SVN commands through a php script. Urban legend has it that there are some modules written to interact with the SVN client directly for PHP, but they are certainly still in the mythical stage at this point and definitely nto suited for mission-critical use. So, my only alternative was to encapsulate some direct system calls to the SVN client with a PHP object in order to utilize its functionality.
Anyways, on to the problems at hand. Below is a list of some of the "wickedness" I have encountered of late in trying to utilize SVN, along with the eventual solutions:
Externally Linked Folder Woes
So, since we utilize a fairly significant amount of base code, whose breadth spans multiple projects across the site, it is natural to want any changes to that code to be replicated accross its many locations. That in mind, its sort of a pain to have to make changes in several places to accomplish that. Therefore, one of the best solutions is to create externally linked folders in SVN. This allows the code to be stored in a single location, but included as part of various repository folders.
In comes trouble. This apparently has a few hiccups, at least in my version of SVN (which by the way I'm forced to get through redhat, so it is a bit outdated from the most recent version). It was noticed, that in order for the working copy to recognize these new externally linked folders, you have to make it jump through a few hoops and do a little dance. First of all, the root folder of the project (in most cases the 'trunk' folder) has to be updated. Well I didn't want to update everything inside it as well, so I was forced to use the -N flag to make it non-recursive. This alone did not do the trick however. I also had to actually copy the new folders into the path in the working copy. Once I did that I was able to call svn update on the linked folders and they appeared in the SVN versioning as if they had always been there. Not sure why that was the case, but I'm told that is fixed in later versions.
Certificate Hostname Mismatch Woes
This is one of the stupidest issues I have encountered as of yet in SVN. As part of my automated deployment tool, I must execute subversion commands from a web script, which runs as the apache user. For security reasons, this user does not have any home folder, shell functionality, or other resources that conventional users do. Subversion commands however, will present an accept dialog for any less than perfect security problems they encounter, which since the web user has no shell functionality, it is impossible to connect as them and permanently accept the certificate.
Here comes the really stupid part. There used to be command flag in the earlier subversion clients that allowed you to ignore certificate warnings and accept them automatically, but it was removed because it was deemed obsolete! Idiotic decision. That means that either the certificate must be perfect (in this case it was self-signed and I was originally getting a warning because the hostname did not match, and because the CA was not trusted), or you must add the CA cert to the list of approved CA's for all clients on the server if you are going to connect through a web script. Not very friendly towards dynamically allowing the addition of new SVN servers.
So to solve this problem, I finally just had to create a new certificate with the proper hostname to solve the hostname warning, and then add the certificate's .crt file to the server hosting the web script, so that it's SVN client would ignore the CA warning error. I won't go through how to create a new certificate, since there are lots of good sites on that (try http://slacksite.com/apache/certificate.html), but I will tell you how to add the .crt file to the list of approved CA's.
To rid yourself of an invalid CA certificate error. on the SVN client server, go to /etc/subversion as root (if the folder does not exist, jsuts create it - I spent a while figuring out you could do that even with older versions of SVN). Copy the .crt file that was used to sign the offending certificate into this folder. Make sure the certificate file is world readable. Now create a file called 'servers' in the same folder (/etc/subversion), or edit the one that is already there. For added security, we only want to accept the CA for the URL of the SVN repository. So, to the 'servers' file, make the following addition (where 'mygroupname' is a name you have chosen for the group, 'host.domain' is the hostname of the server hosting the SVN repository, and 'host.domain.crt' is the name of the certificate file that you copied over):
[groups]
mygroupname = host.domain
[mygroupname]
ssl-authority-files=/etc/subversion/host.domain.crt
Now, when you connect to the repository on the specified server you should no longer get either of those certificate error warnings.
Subversion HTTP Passwords Stored in Plaintext
The final piece of subversion perversion that I want to share has to do with the fact that HTTP passwords used to connect to an SSL encrypted repository URL, are stored in plaintext on the client machine! Amazing! I know that HTTP authentication is passed in plaintext, but why would anyone use that without tunnelling it through SSL! That's even how it is recommended in the SVN documentation! So, what I don't understand, is why the client wasn't written to encrypt, or at least hash those passwords when caching them on the client. If you want to taste of what I am talking about, connect your SVN client to an HTTP or HTTPS repository location, and then check out '/home/username/.subversion/auth/svn.simple'. Do a 'cat' on one of the files in that folder and you will see the username and password plainly shown! I'm sorry, but that just amazes me as to why people still do that in this day and age!
1 Comments:
Let me just say, that is the most perverse and heinous thing I've ever heard! I've never been so disgusted in my life!
But what disgusts me the most is, I hardly understood a word of that. Time for me to go back to geek school.
Post a Comment
<< Home