Jan 30, 2013
Couldn't miss this, which I think is quite appropriate here ;) Enjoy this short Video published in today's APOD
Oct 02, 2009
Apache2 can use several authentication methods and options in order to allow access to the same resource, configured in a single VirtualHost.
In the following case i've illustrated how i solved the needing to access via
two different authentication/authorization methods the same
<Location></Location> by users registered on different authentication
systems and so to have different kinds of permissions on the resource, in this
case, subversion repositories.
The developers team of the company i actually work for, expressed the needing to give external occasional supporting developers, access to our subversion repositories made available through Apache2 HTTPS connection, behind a Nginx reverse proxy. They didn't want to register the external developers in our corporate SSO (OpenLDAP), instead they wanted to have them in separate authentication/authorization system, able to manage permissions on the repositories too.
Ubuntu 8.04 LTS in KVM virtual machine
Subversion 1.5.1
Apache2 mpm-itk
OpenSSL
Apache2 modules, basically the following:
auth_basic_module
mod_authn_file
authnz_ldap_module
dav_module
dav_svn_module
ldap_module
authz_svn_module
authn_alias_module, which is in the core as demonstrated by:
root@vm:/etc/apache2/sites-available# dpkg -S mod_authn_alias.so
apache2.2-common: /usr/lib/apache2/modules/mod_authn_alias.so
An OpeLDAP server somewhere, already giving authentication;
Subversion installed and functional on the same machine and already giving privileges management through a svn_auth_file.
This functionality is available by using the apache2 directive:
AuthnProviderAlias via the authn_alias_module obtained installing the
package apache2.2-common. The directive's operating context is: server config,
so it has to be inserted, in the case of Debian-based systems, in the
/etc/apache2/apache2.conf.
The purpose is to to configure a set of authentication methods that can be
made available to the VirtualHost's Location directives. The directive allows
to define the method itself, a name for a single method and other specific
configuration parameters, by specifing a directive for every single
authentication method to be used. The AuthBasicProvider directive can then
be used in the Location directives to make effectively use of them listing
names after it. In this way the administrator can use a mix of authentication
methods as needed per VirtualHost's Locations. Other specific configuration
can be used inside the Location directive itself, as the LDAP DN, paths to
privileges files and so on.
For this case i've used apache2-mpm-itk, which is stated to be still in
experimental stage, so use it at your own risk, surely there are other methods
to make an Apache2 VirtualHost run under a specified user. Furthermore there
has to be take into consideration that the mpm-itk is a de facto version of a
prefork, so: no threading.
The choice to make this VirtualHost running under a specified user is to give DAV physical access to the repositories in a permissions' coherent way, since the readings/writings operations are made by dav_svn_module installed via libapache2-svn Debian package.
The "AssignUserID uid gid" allows to specify, respectively, user name and group name to run under and its specific to mpm-itk
The usage of "UseCanonicalName on" makes DAV correctly identifying names to access the repositories since i'm using apache as a backend, in this way it correctly determines names as the Nginx reverse proxy passes through.
External users are authenticated on a htpasswd file, their permissions and privileges on the repositories are configured in a svn_auth_file, which defines users, groups of users and kind of permissions, it's related to only subversion, and in this case, is the second authentication/authorization system.
A configuration example follows:
apache2.conf excerpt:
1 2 3 4 5 6 7 8 9 10 | <AuthnProviderAlias ldap ldap1 > AuthBasicProvider ldap # just an example AuthLDAPURL "ldap://IP_or_DOMAIN/ou=organization-unit,DC=domain,DC=tld?uid?sub?" </AuthnProviderAlias> <AuthnProviderAlias file svnfile> AuthUserFile /path/to/your/.htpasswd AuthzSVNAccessFile /path/to/your/svn_conf/authz_access.conf </AuthnProviderAlias&> |
VirtualHost.conf excerpt(replace the file name accordingly):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <VirtualHost *> ServerName scm.domain.tld ServerAdmin sysadm@domain.tld ErrorLog /var/logs/error CustomLog /var/logs/access combined # accept up to 10MB file size uploads LimitRequestBody 10485760 # assign the uid and gid user to this VH AssignUserID uid gid UseCanonicalName on <Location /repos> DAV svn SVNParentPath /path/to/svn_repos_dir SVNListParentPath on AuthBasicProvider ldap1 svnfile AuthType basic AuthName "Your REALM name here" AuthzLDAPAuthoritative on # owned by uid AuthzSVNAccessFile /path/to/conf/authz_access.conf require valid-user require ldap-group cn=gid,ou=group,dc=domain,dc=tld </Location> </VirtualHost> |
In this way it'll be possibile access the repositories with a URL like https://domain.tld/repos/repo_name by using a registered user name in either OpenLDAP or htpasswd file when the authentication credentials will be requested. The users in the htpasswd file will be subject to the permissions defined in the SVN authentication file /path/to/conf/authz_access.conf.
The configuration illustrated here is just A solution not THE solution, i think there can be find other ways of accomplishing the same results, so use the above instructions at your own risk, i'm not responsible of what the reader does on her/his administered systems.
HTH,
Gianluca
The AuthnProviderAlias directive
The AuthBasicProvider directive
The authz_svn_module configuration directives
The dav_svn_module configuration directives
The dav_svn_module Configuration Directives, from the svnbook
The authz_svn_module directives, from the svnbook
SVN Path-Based Authorization, from the svnbook
Nov 22, 2008
It's possibile to configure an HTTPS access to Subversion repositories, using a webserver like Apache2.2, with WebDAV functionalities provided by the DAV apache modules. The SSL connection provides a secure tunnel and users will authenticate against a OpenLDAP directory service authenticating only users pertaining to a allowed group.
The HTTPS will be made available by a front-end web server, Nginx, HTTP reverse-proxying to Apache2 on port 80, that will take care of users authetication and authorization, accessing the subversion repositories. The Apache2.2 virtual host will be running as a system user owning the repositories and thus having the needed read and write permissions.
Nginx will be listening on the public IP interface on port 443 (or another port of choice) making the SSL connection using self signed certificate and key. Apache2.2 can be installed on the same machine and listening on the loopback, or can be installed on another virtual or physical machine in a private IP network, listening on port 80. Having the back-end server on a private network is a choice of network design, it can be varied on particular needings as well, but it will be the only one discussed here.
The operating system of choice is GNU/Linux, having a SLES10.3 SP1 running on the front-end machine and a Ubuntu 8.10 server edition on the back-end server.
In the Nginx compilation and installation wiki page there's thorough documentation giving details on the process, here will be showed an example of how to compile with the required SSL module, so get in the /usr/local/ directory and download the sources tar.gz package:
wget http://sysoev.ru/nginx/nginx-0.6.32.tar.gz
and unpack it:
tar -xzf nginx-0.6.32.tar.gz
before running the configure script it can be useful to check for latest updates to the configuration process:
./configure --help
get in the source directory and run the configure script:
./configure --with-http_ssl_module
and then compile:
make
make install
the contents of the sources dir should be as follows:
1 2 3 4 5 6 7 | client_body_temp/ conf/ fastcgi_temp/ html/ logs/ proxy_temp/ sbin/ |
having the nginx binary in the sbin/ directory.
An init script is needed in order to manage the sevice and correctly boot-up:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #! /bin/sh ### BEGIN INIT INFO # Provides: nginx # Required-Start: $all # Required-Stop: $all # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: starts the nginx web server # Description: starts nginx using start-stop-daemon ### END INIT INFO PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/local/sbin/nginx NAME=nginx DESC=nginx test -x $DAEMON || exit 0 # Include nginx defaults if available if [ -f /etc/default/nginx ] ; then . /etc/default/nginx fi set -e case "$1" in start) echo -n "Starting $DESC: " start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/nginx.pid --exec $DAEMON -- $DAEMON_OPTS echo "$NAME." ;; stop) echo -n "Stopping $DESC: " start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/nginx.pid echo "$NAME." ;; restart|force-reload) echo -n "Restarting $DESC: " start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/nginx.pid --exec $DAEMON sleep 1 start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/nginx.pid --exec $DAEMON -- $DAEMON_OPTS echo "$NAME." ;; reload) echo -n "Reloading $DESC configuration: " start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/local/nginx/logs/nginx.pid \ --exec $DAEMON echo "$NAME." ;; *) N=/etc/init.d/$NAME echo "Usage: $N {start|stop|restart|force-reload}" >&2 exit 1 ;; esac exit 0 |
edit it as needed then copy the above script in the /etc/init.d/ directory and add it to the default runlevels using chkconfig command:
`chkconfig --add /etc/init.d/nginx
` as a facility, create the symlink to the boot script in the SLES style:
`ln -s /etc/init.d/nginx /usr/sbin/rcnginx
` before starting the Nginx web server, a minimum configuration of the main nginx.conf file is needed, giving the webserver a name through the server_name directive; if a DNS hostname is not yet available, it's possibile to configure a static route (fake host in the /etc/hosts file in the local desktop computer in the case of unix based OSes) just for testing/learning before releasing, and make sure the listen directive is, for now, with value 80 and then, as root,
start the server:
`root# rcnginx start
` and using a web-browser verify that a 200 http response is received, usually displaying the default static page.
A private key and certificate for the nginx server are needed in order to make the SSL connection possible, in this a self signed-certificate will be created and used, it's assumed that a OpenSSL installation is already available in the running SLES10.
Generating the key:
`root# openssl genrsa -out privkey 1024
` generating the certificate request:
`root# openssl req -new -key privkey -out signing_request
` note: a few params will be requested, the most important is the 'Common Name' which has to be the server name otherwise the certificate will not be accepted, having the nginx unable to initiate the SSL connection itself.
generating the self-signed certificate:
`root# openssl x509 -req -days
` issuing the last opennsl command will generate the certificate to be configured in the nginx server, for a deeper and complete OpenSSL documentation refer to the local installation Docs and/or make a websearch.
In order to have Nginx correctly initiate and establish a HTTPS connection, the generated certificate file and key must be installed.
The Virtual Hosts configuration will be kept in separate files and location than the nginx.conf, in a directory contained under the conf/ dir of the Nginx installation:
1 2 3 | /usr/local/nginx/conf/sites-available /usr/local/nginx/conf/sites-enabled |
as can be noted the Debian style won. In the sites-available directory will be put the Virtual Host files holding the host specific configurations, while in the sites-enabled will be put the symlinks pointing to the hosts wanted to be live. In the nginx.conf main configuration file will be specified the directive to include the sites-enabled contents, as following:
1 2 3 | # Virtual hosts a la Debian include sites-enabled/*; |
in the sites-available directory, copy a file as the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | server { listen 443; server_name hostname.domain; ssl on; ssl_certificate /etc/ssl/certs/server_certificate; ssl_certificate_key /etc/ssl/certs/privkey; access_log logs/hostname.domain_access.log; error_log logs/hostname.domain_error.log; location / { root html; index index.html index.htm; # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # proxy_set_header Host $http_host; # proxy_pass http://IP_Addr; # proxy_redirect off; set $dest $http_destination; if ($http_destination ~ "^https://(.+)") { set $dest http://$1; } } } |
by reading the ssl_certificate and ssl_certificate_key directives values, the locations of certificate file and key can be found, after editing the configuration file, symlink this file from the sites-enabled directory to make them included and restart the nginx server.
After restarting nginx, open a https connection in the web-browser and verify the SSL connection working without errors.
The Nginx configuration can be considerd complete and working, later on nginx will be configured to reverse-proxy to apache2.
In order to have every Virtual Host running under a separate user, apache2 mpm-itk will be installed on the Ubuntu back-end server:
`root# aptitude install apache2-mpm-itk
`
On the machine hosting the central repositories, there will be the need to create and administer the subversion repositories themselves, for this reason a special user, dedicated to the purpose, will be created:
1 2 3 | root# addgroup --system scm-local root# adduser --system --home /path/to/repos -g scm-local scm |
in this way, the directory trees starting from the scm home dir will have a coherent permissions scheme, and the scm user will be the user the VirtualHost will be running as. The group is named scm-local because there is a already created and populated LDAP group named scm.
The basic apache2 virtual host configuration will be similar to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <VirtualHost IP_addr:80> ServerName hostname.dominio ErrorLog /path/to/logs/scm_error CustomLog /path/to/logs/scm_access combined # assign the scm user to this VH AssignUserID scm scm-local # only needed for testing DocumentRoot /scm/home/dir </VirtualHost> |
after testing the acces, on the local listening IP interface, using a web- browser(elinks) and verified that everything is running, the next step will be to configure Nginx to reverse proxy to apache2
In the nginx virtual host configuration file uncomment the proxy_* directives and comment the root and index directives and test by accessing the https://hostname.domain from the outside, the default apache2 static page, in the DocumentRoot should be displayed while apache should give a 200 http response.
It is now time to get on the Apache2.2 SVN and LDAP configuration.
On the back-end server install the modules for LDAP authentication, as root:
root# a2enmod authnz_ldap
then modify the virtual host configuration:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <VirtualHost IP_addr:80> ServerName hostname.domain ErrorLog /path/to/logs/error CustomLog /path/to/logs/access combined # assign the scm user to this VH AssignUserID scm scm-local DocumentRoot /scm/home/dir UseCanonicalName on AuthType basic AuthUserFile /dev/null AuthBasicProvider ldap AuthName "SCM auth" AuthzLDAPAuthoritative on AuthLDAPURL "ldap://IP_addr:PORT/ou=people,DC=hostname,DC=domain?uid?sub?" require valid-user require ldap-group cn=Group_name,ou=group,dc=hostname,dc=domain </VirtualHost> |
as usual, make a test accessing the hostname.domain trying to authenticate a user with correct credenials and group membership, then with un unprivileged user and be sure to get success and error responses.
as root:
root# a2enmod dav_svn
and modify the virtual host configuration as following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <VirtualHost IP_addr:80> ServerName hostname.domain ErrorLog /path/to/logs/error CustomLog /path/to/logs/access combined # assign the scm user to this VH AssignUserID scm scm-local UseCanonicalName on <Location /repos> DAV svn SVNParentPath /path/to/repos SVNListParentPath on AuthType basic AuthUserFile /dev/null AuthBasicProvider ldap AuthName "SCM auth" AuthzLDAPAuthoritative on AuthLDAPURL "ldap://IP_Addr:Port/ou=people,DC=hostname,DC=domain?uid?sub?" require valid-user require ldap-group cn=Scm,ou=group,dc=hostname,dc=domain </Location> </VirtualHost> |
after these changes to the configuration it's possible to use the repositories as either using the svn CLI or web access. The use of UseCanonicalName on is in conjunction with the set destination Nginx configuration, in order to make DAV correctly operating on files and destinations.
Since Subversion 1.5 has been released, i took the chance to migrate the repositories to the new version:
on the back-end server, which hosts the SVN repositories, become the 'scm' user and start creating the new repositories:
scm$ svnadmin create repo1
it is a good time now for testing the access to the newly created repository and make some test commit/update just to be sure all the structure is working as wanted;
to migrate the repositories a dump of the old ones is needed, so get on the old svn central repositories machine and issue a dump:
scm$ svnadmin dump repo_name > repo_name_oldversion.dump
and transfer the file containing the dump on the back-end server in the 'scm' home directory, maybe by using a scp copy;
before loading the dump create the repository named as the old one which the dump comes from:
scm$ svnadmin create repo_name
and then load the dump:
scm$ svnadmin load repo_name < repo_name_oldversion.dump
this was a brief example of subversion dump/load cycle.
This was quite a fast tour in configuring such a structure, by following it are not excluded issues, but in this way it should be possible to use a subversion repositories collection by either svn cli or web-access.
Hope it helps.
Moon at 30:20:43.6, 187:32:51.3 observing from Rome, IT
Powered by Moonwatcher.it ShortPosts.