Feb 21 2010

Debian, Subversion, WebDAV, Active Directory

Today i had to implement WebDAV, subversion with Active Directory authentication. I started with the default debian/lenny installation of apache omitting Debian’s libapache2-svn package because i wanted to install the newest subversion release and use it’s modules instead.

Compiling subversion sources against Debian libs is pretty straightforward, I grabbed the newest source tarball from subversion’s web site, unpacked it, and compiled the same (x.x.x represents the version, in this case the version is 1.6.9).

# tar xzf subversion-x.x.x.tar.gz
# cd subversion-x-x-x
# ./configure --prefix=/usr/local/subversion \
> --with-apxs=/usr/bin/apxs2 --with-apr=/usr/bin/apr-config \
> --with-apr-util=/usr/bin/apr-config --with-neon=/usr \
> --with-sasl=/usr/lib/sasl2
# make
# make install

Once the compiling/installing process is over, we need to enable required apache2 modules:

# a2enmod dav_svn
# a2enmod authnz_ldap

After the step described above, i needed to edit/create some configuration files for newly enabled modules. First one in line was “dav_svn.conf” configuration file, followed by “authz” file which is mentioned after the configuration directive “AuthzSVNAccessFile“, and represents a standard subversion authorization mechanism file.

The “dav_svn.conf” file:

<Location /svn>
        DAV svn
        SVNParentPath /path/to/parent/path
        SVNListParentPath on
        AuthzSVNAccessFile /path/to/parent/path/conf/authz
 
        AuthBasicProvider ldap
        AuthType Basic
        AuthName "SVN"
        AuthLDAPURL "ldap://IP_OF_THE_DOMAIN_CONTROLLER:389/dc=DOMAINNAME,dc=TLD?sAMAccountName"
        AuthLDAPBindDN "cn=ADMINUSER,cn=Users,dc=DOMAINNAME,dc=TLD"
        AuthLDAPBindPassword supersecretpassword
 
        require valid-user
</Location>

Apache might complain after enabling “mod_authnz” module, so i made it to load after “dav_svn” module. In order to accomplish this, i simply added the “LoadModule” directive into the configuration file named “dav_svn.load“.

LoadModule dav_svn_module /usr/lib/apache2/modules/mod_dav_svn.so
LoadModule authz_svn_module /usr/lib/apache2/modules/mod_authz_svn.so

And that is it, restarted the apache daemon and accessed our WebDAV repo !

http://servername/svn

Feb 11 2010

Archiva: The Build Artifact Repository Manager

So, last weekend i was upgrading our main production server to a 64bit version of Debian linux distribution. One of the tasks after the upgrade was to implement Archiva: The Build Artifact Repository Manager and have it authenticate users against our Active Directory server.

The procedure is quite simple, however, the documentation provided on their site makes baby Jesus cry. Below i will describe the steps to get this done, as well as using mySQL instead of the default derby database.

These steps are made on Debian/Lenny, however installation/configuration of the standalone archiva package wouldn’t differ on other linux kernel based distributions.

Ze steps:

Download and unpack archiva to a folder of your choice, i used /opt for the application package and /usr/local/archiva/ for the configuration files. This separation is done by issuing a simple cp or mv command (e.g. mv /opt/archiva/conf /usr/local/archiva/).

Instead of derby database i chose mySQL (which is running locally). To get this working i needed to edit a few files, first file to edit was /etc/profile where it was needed to add $ARCHIVA_BASE variable which will later on be used by the archiva start up script (conveniently located in /opt/archiva/bin/archiva). Using my favorite text editor, i added the line export ARCHIVA_BASE=/usr/local/archiva.

Next step was to configure mySQL connections. To do this, changes to the jetty.xml configuration file located inside the /usr/local/archiva/conf/ directory were required.

The original section of the jetty.xml configuration file (derby database):

  <!-- Archiva database -->
  <New id="archiva" class="org.mortbay.jetty.plus.naming.Resource">
      <Arg>jdbc/archiva</Arg>
      <Arg>
       <New class="org.apache.commons.dbcp.BasicDataSource">
             <Set name="driverClassName">org.apache.derby.jdbc.EmbeddedDataSource</Set>
             <Set name="url">jdbc:derby:<SystemProperty name="appserver.base" default=".."/>/data/databases/archiva</Set>
             <Set name="username">sa</Set>
             <Call name="addConnectionProperty">
               <Arg>create</Arg>
               <Arg>true</Arg>
             </Call>
       </New>
      </Arg>
  </New>
 
  <New id="archivaShutdown" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>jdbc/archivaShutdown</Arg>
    <Arg>
      <New class="org.apache.commons.dbcp.BasicDataSource">
             <Set name="driverClassName">org.apache.derby.jdbc.EmbeddedDataSource</Set>
             <Set name="url">jdbc:derby:<SystemProperty name="appserver.base" default=".."/>/data/databases/archiva</Set>
             <Set name="username">sa</Set>
              <Call name="addConnectionProperty">
               <Arg>shutdown</Arg>
               <Arg>true</Arg>
             </Call>
       </New>
    </Arg>
  </New>
 
  <!-- Users / Security Database -->
 
  <New id="users" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>jdbc/users</Arg>
    <Arg>
      <New class="org.apache.derby.jdbc.EmbeddedDataSource">
        <Set name="DatabaseName"><SystemProperty name="appserver.base" default=".."/>/data/databases/users</Set>
        <Set name="user">sa</Set>
        <Set name="createDatabase">create</Set>
      </New>
    </Arg>
  </New>
 
  <New id="usersShutdown" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>jdbc/usersShutdown</Arg>
    <Arg>
      <New class="org.apache.derby.jdbc.EmbeddedDataSource">
        <Set name="DatabaseName"><SystemProperty name="appserver.base" default=".."/>/data/databases/users</Set>
        <Set name="user">sa</Set>
        <Set name="shutdownDatabase">shutdown</Set>
      </New>
    </Arg>
  </New>
</Configure>

mySQL connection is configured as follows:

  <!-- Archiva database -->
<New id="archiva" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>jdbc/archiva</Arg>
    <Arg>
      <New class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
        <Set name="serverName">localhost</Set>
        <Set name="databaseName">archiva</Set>
        <Set name="user">database_username</Set>
        <Set name="password">database_user_password</Set>
      </New>
    </Arg>
  </New>
 
  <New id="archivaShutdown" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>jdbc/archivaShutdown</Arg>
    <Arg>
      <New class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
        <Set name="serverName">localhost</Set>
        <Set name="databaseName">archiva</Set>
        <Set name="user">database_username</Set>
        <Set name="password">database_user_password</Set>
      </New>
    </Arg>
  </New>
 
  <!-- Users / Security Database -->
 
  <New id="users" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>jdbc/users</Arg>
    <Arg>
      <New class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
        <Set name="serverName">localhost</Set>
        <Set name="databaseName">archiva</Set>
        <Set name="user">database_username</Set>
        <Set name="password">database_user_password</Set>
      </New>
    </Arg>
  </New>
 
  <New id="usersShutdown" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>jdbc/usersShutdown</Arg>
    <Arg>
      <New class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
        <Set name="url">jdbc:mysql://localhost/archiva</Set>
        <Set name="user">database_username</Set>
        <Set name="password">database_user_password</Set>
      </New>
    </Arg>
  </New>
</Configure>

Of course, i don’t need to point out that at this point there is no “archiva” database in the mySQL yet (you need to create the database, as well as the user and grant privileges to that user), nor does the archiva application come with the appropriate prepackaged connector for the mySQL database.

Obtain the mySQL connector, unpack it and move the JDBC driver named mysql-connector-java-5.0.8-bin.jar to the appropriate directory, in this case the appropriate directory is /opt/archiva/lib/.

Next we configure the Active Directory connection. The connection is established by modifying two configuration files.

First we need to change the file named application.xml located in the /opt/archiva/apps/archiva/WEB-INF/classes/META-INF/plexus/ directory.

The original file sections that need to be modified look as presented below (i omitted the commentaries, including only the sections that matter), just under the line

<!-- START SNIPPET: ldap -->

Commented sections need to be uncommented and some additions need to be done:

    <!-- component>
      <role>org.codehaus.plexus.redback.common.ldap.connection.LdapConnectionFactory</role>
      <role-hint>configurable</role-hint>
      <implementation>org.codehaus.plexus.redback.common.ldap.connection.ConfigurableLdapConnectionFactory</implementation>
      <requirements>
        <requirement>
          <role>org.codehaus.plexus.redback.configuration.UserConfiguration</role>
        </requirement>
      </requirements>
    </component-->
 
    <!--
 
    <!-- component>
      <role>org.codehaus.plexus.redback.common.ldap.UserMapper</role>
      <role-hint>ldap</role-hint>
      <implementation>org.codehaus.plexus.redback.common.ldap.LdapUserMapper</implementation>
      <configuration>
        <email-attribute>email</email-attribute>
        <full-name-attribute>givenName</full-name-attribute>
        <password-attribute>userPassword</password-attribute>
        <user-id-attribute>cn</user-id-attribute>
        <user-base-dn>o=com</user-base-dn>
        <user-object-class>inetOrgPerson</user-object-class>
      </configuration>
      <requirements>
        <requirement>
          <role>org.codehaus.plexus.redback.configuration.UserConfiguration</role>
        </requirement>
      </requirements>
    </component-->
 
    <!--

This is how the sections look after the modifications:

    <component>
      <role>org.codehaus.plexus.redback.common.ldap.connection.LdapConnectionFactory</role>
      <role-hint>configurable</role-hint>
      <implementation>org.codehaus.plexus.redback.common.ldap.connection.ConfigurableLdapConnectionFactory</implementation>
      <configuration>
        <hostname>hostname_or_IP_address_of_the_domain_controller</hostname>
        <port>389</port>
        <baseDn>cn=Users,dc=domain,dc=tld</baseDn>
        <contextFactory>com.sun.jndi.ldap.LdapCtxFactory</contextFactory>
        <bindDn>cn=Administrator,cn=Users,dc=domain,dc=tld</bindDn>
        <password>super_secret_password</password>
      </configuration>
       <requirements>
         <requirement>
           <role>org.codehaus.plexus.redback.configuration.UserConfiguration</role>
         </requirement>
       </requirements>
    </component>
 
    <component>
      <role>org.codehaus.plexus.redback.common.ldap.UserMapper</role>
      <role-hint>ldap</role-hint>
      <implementation>org.codehaus.plexus.redback.common.ldap.LdapUserMapper</implementation>
      <configuration>
        <email-attribute>email</email-attribute>
        <full-name-attribute>cn</full-name-attribute>
        <password-attribute>unicodePwd</password-attribute>
        <user-id-attribute>sAMAccountName</user-id-attribute>
        <user-base-dn>cn=Users,dc=domain,dc=tld</user-base-dn>
        <user-object-class>user</user-object-class>
      </configuration>
      <requirements>
        <requirement>
          <role>org.codehaus.plexus.redback.configuration.UserConfiguration</role>
        </requirement>
      </requirements>
    </component>

After we have modified the files above, we need to create or modify the file named security.properties located in the /opt/archiva/apps/archiva/WEB-INF/classes/org/apache/maven/archiva/ directory with the following entries:

user.manager.impl=ldap
ldap.bind.authenticator.enabled=true
redback.default.admin=Administrator
#redback.default.guest=
security.policy.password.expiration.enabled=false

That is it, start your archiva application by issuing:

# /opt/archiva/bin/archiva start

Open your browser and point it to the URL
http://IP_of_the_box_running_archiva:8080/archiva

Log in using your Active Directory administrator account ! VoilĂ  !