Tuesday, July 28, 2009

[updated] Subversion and Apache with PAM

First of all, I'm not an SELinux expert, but it really annoys me from time to time. Let me start with the whole story.

I'm simply trying to install and configure an SVN server, or subversion with you will. But I definitely want neither something like plain text authentication nor an access without authentication. Therefore I was trying to configure an access tunnelled through SSH (svn+ssh). I tried every cookbook recipe that I could put my hands on. Nothing worked. Then I started trying an SVN+Apache+SSL configuration. A little further but the authentication wasn't working. Then I figured it out: SELinux was the one to blame.

Ok, now that I just whined about SELinux lets go to the problem and how to solve it.

Problem:

- Subversion server (SVN)
- Authentication through system authentication, i.e., the linux users should have access to the SVN without requiring an extra password (the local authentication solution was no good)
- Secure access to the SVN (through SSH or HTTPS)

Solution:

1. VERY, but VERY, important FIRST step:

- reduce the SELinux enforcement level. Adjust the /etc/sysconfig/selinux file to:

SELINUX=permissive # this is definitely enough

1.1. Restart your machine. This is absolutely necessary. If you don't, none of the things will work until you do it.

2. Install the required packages:

2.1. Subversion server:

#---
yum -y install \
subversion
#---


2.2. Cyrus SASL sever (to act as a proxy for the authentication):

#---
yum -y install \
cyrus-sasl \
cyrus-sasl-md5 \
cyrus-sasl-plain
#---


2.3. The Apache server an its modules:

#---
yum -y install \
httpd \
mod_auth_shadow \
mod_auth_pam \
mod_dav_svn \
mod_ssl
#---


3. Setup your SVN repository, locally (you can visit the subversion home-page and take a look on the documentation) at, for the sake of an actual example, /var/svn/ :

#---
svnadmin create /var/svn/
svn mkdir -m "Initial setup: main development tree" file:///var/svn/trunk
svn mkdir -m "Initial setup: branches" file:///var/svn/branches
svn mkdir -m "Initial setup: tagged versions" file:///var/svn/tags
#---


3.1. Edit your SVN configuration file /var/svn/conf/svnserve.conf :

[general]
anon-access = none
auth-access = write
realm = test

[sasl]
use-sasl = true
min-encryption = 0
max-encryption = 256


4. Setup the users groups, it is necessary to have access to the SVN repository:

#---
groupadd svnusers
chgrp -R svnusers /var/svn/
chmod -R ug+rw /var/svn/
usermod -a -G svnusers <user-name that suppose to have access to the SVN>
#---


OBS.: Remember, if you are the user in question you need to logout before trying to access the SVN. The change will only take effect on the NEXT login.

4.1. Setup the apache user to be able to read the /etc/shadow file:

#---
groupadd shadow-readers
usermod -a -G shadow-readers apache
chgrp shadow-readers /etc/shadow
chmod g+r /etc/shadow
#---


OBS.: This is security problem, minor, but still. Be aware of that!

5. Setup the Cyrus SASL:

5.1. The SVN part of the SASL, in the file (which you need to create) /etc/sasl2/svn.conf:

#---
cat > /etc/sasl2/svn.conf << __END__ pwcheck_method: saslauthd __END__ #---


5.2. The SASL Server to use PAM as the authentication method, in the file /etc/sysconfig/saslauthd :

MECH=PAM

6. Setup the Apache server:

6.1. Add the apache user to the svnusers group, this is necessary for the apache to be able to read the files to show you:

#---
usermod -a -G svnusers apache
#---


6.2. Change Apache default group in the file /etc/httpd/conf/httpd.conf to be the svnusers:
Group svnusers

OBS.: Note that this is an alternative solution. The convetional solution would be to set the owner of your repository to be the apache user:

#---
chown -R apache:svnusers /var/svn/
#---


6.3. I suppose you want an SSL server then edit the file /etc/httpd/conf.d/subversion.conf :

#---
cat > /etc/httpd/conf.d/subversion.conf << __END__

LoadModule dav_module modules/mod_dav.so

LoadModule dav_svn_module modules/mod_dav_svn.so

LoadModule auth_pam_module modules/mod_auth_pam.so

LoadModule ssl_module modules/mod_ssl.so


<Location /repos> # <<<<<<< PAY ATTENTION TO THIS

DAV svn

# v----- PAY ATTENTION TO THIS

SVNPath /var/svn/

AuthType Basic

AuthPAM_Enabled on

AuthShadow on

AuthName "test"

Order allow,deny

Allow from all

# since you are restricting to the svnusers ...

Require group svnusers # <<<<<<< PAY ATTENTION TO THIS

# Limit write permission to list of valid users.

<LimitExcept GET PROPFIND OPTIONS REPORT>

# Require SSL connection for password protection.

SSLRequireSSL

Require user valid-username

</LimitExcept>

</Location>

__END__

#---


7. Setup the PAM part:

7.1. The PAM file for the SVN, in the file /etc/pam.d/svnserve :

#---
cat > /etc/pam.d/svnserve << __END__

#%PAM-1.0

auth required pam_sepermit.so

auth include system-auth

account required pam_nologin.so

account include system-auth

password include system-auth

__END__

#---


OBS.: This is the part that will be used when accessing the SVN through an SSH connection, like:

#---
svn list svn+ssh://<user-name that suppose to have access to the SVN>@localhost/var/svn
#---


7.2. The PAM file for Apache, in the file /etc/pam.d/httpd (the same as above):

#---
cat > /etc/pam.d/httpd << __END__ #%PAM-1.0

auth required pam_sepermit.so

auth include system-auth

account required pam_nologin.so

account include system-auth

password include system-auth

__END__

#---


OBS.: This is the part that will be used when accessing in the browser: https://localhost/repos/

8. Put the services to start at boot time:

#---
chkconfig --level 345 httpd on
chkconfig --level 345 saslauthd on
chkconfig --level 345 sshd on
#---


8.1. Start the services now to test them:

#---
service httpd start
service saslauthd start
service sshd start
#---


8.2. Check if the services are actually on and serving:

OBS.: For this part you will need the "nc", so:

#---
yum -y install \
nc
#---


For all tests the response should be:

Connection to localhost port [tcp/https] succeeded!

#---
nc -z localhost 22 || echo "SSH is not running" # ssh
nc -z localhost 80 || echo "HTTP is not running" # http
nc -z localhost 443 || echo "HTTPS is not running" # https
#---


9. Check with a real example:

9.1. SSH access:

#---
svn list svn+ssh://<user-name that suppose to have access to the SVN>@localhost/var/svn/
#---


9.1.1. If you have something to import already:

#---
svn import svn+ssh://<username that suppose to have access to the SVN>@localhost/var/svn/trunk/ -m "Import version"
#---


OBS.: Check it out if it is there by running the command before this last on.

9.2. Https access (in a browser)

https://localhost/repos/

OBS.: It will ask your user-name and password, provide it and this should let you see the repository

9.3. Eclipse url:

svn+ssh://localhost/var/svn/

10. Possible problems:

10.1. Nothing works. Did you reboot your machine, as said in step 1.1?
10.2. No other machine, besides the one where the server is, can access the repository. Check the IPTABLES (out of the scope of this post)
10.3. Permission denied. Did you logout before trying to access (see OBS in step 4)
10.4. Some other problem. Check the following log files:

/var/log/messages # for daemon startup problems
/var/log/secure # for ssh/authentication errors
/var/log/audit/audit.log # typically for SELinux errors and general permission errors
/var/log/httpd/error_log # for regular http errors
/var/log/httpd/access_log # for regular http access log
/var/log/httpd/ssl_error_log # for https errors
/var/log/httpd/ssl_access_log # for https access log

10.4.1. Increase the log verbosity:

A. SASL: add the following line to the file /etc/sasl2/svn.conf:
log_level: 7 # the maximum log level

B. PAM: add, after each line in the PAM files, /etc/pam.d/{svnserve,httpd}, the "debug" string, like in:
auth required pam_sepermit.so debug

C. HTTP: edit the file /etc/httpd/conf/httpd.conf and change the "LogLevel" line to the following:
LogLevel debug

D. Restart all services and start analysing the log files.
#---
service httpd restart
service saslauthd restart
#---


[update]
Windows Eclipse users cannot benefit from this directly, they need an extra step. The procedure is at: http://www.woodwardweb.com/java/howto_configure.html or at http://stackoverflow.com/questions/620223/svn-ssh-question-in-windows

The basic configuration is to set a new environment variable for the SVN_SSH shell:

1. Download and install TortoiseSVN (link here)
2. Set-up the SVN_SSH variable:

Start -> Control Panel -> System -> Advanced (Tab) -> Environment Variables (Button)

2.1. At "User Variables" click at New... and fill the fields:

Variable name: SVN_SSH
Variable value: C:\\Program Files\\TortoiseSVN\\bin\\TortoisePlink.exe -l <ssh username>

OBS1.: Notice that the path may change according to your installation or windows language.

OBS2.: Do NOT forget the "-l <ssh username>" part or else you will be asked about your login for each and every file you check out in eclipse.

3. Set-up Eclipse:

3.1. Add Subclipse:
Update site: http://subclipse.tigris.org/update_1.6.x

3.2. Set-up SVN modus to use SVNkit:
Window -> Preferences -> Team -> SVN
SVN Interface:

4. To remove Eclipse repository "remembering" data, remove all: <path to workspace>/.metadata/.plugins/org.tigris.subversion.subclipse.*
5. Also remove the $ECLIPSE_HOME/configuration/org.eclipse.core.runtime/.keyring (reference here)

No comments: