Posts Tagged ‘Security’

Take Back Control: Using LDAP for SCM Authentication

May 15th, 2008

Yesterday, just for fun, I counted the number of times that I logged into a computer or website. Once to login to my PC. Once more to connect to the company network. Three times for the 3 different UNIX boxes I needed to work with. And (if you promise not to tell my boss) once to login to a popular online shopping site to cancel a book order that apparently was lost in shipping. That’s six times in a day – and a slow day at that.

All this logging in got me thinking about security, authentication and of course, software configuration management (SCM) systems. Most SCM users, unless they are in the computer security business or are otherwise paranoid, don’t think about what goes on when they type in their user name and password and press Enter. In this post, we’ll peel back the covers a bit and show how you can use LDAP as the authentication mechanism for the AccuRev SCM system.

Starting with version 4.6, AccuRev introduced the notion of a ‘custom’ authentication mechanism. If you boil it all down, there are only three things that you need to do in order to use LDAP authentication with AccuRev:

1. Tell the AccuRev server that you want to use custom authentication

2. Create users in AccuRev and in LDAP

3. Write a special AccuRev trigger that authenticates the users against an LDAP server

Let’s look at each of these in turn. First, a word of caution. As with any change to a shared production system, it is best to practice this in a safe environment. If you don’t have a spare AccuRev server laying around, you can always download the free 30 day, 5-user evaluation kit and use it to fine tune your new authentication process.

Now to the details. To tell the AccuRev server that you want to bypass the built-in authentication mechanism and use a custom method, execute the following command:

accurev authmethod custom

Next, you’ll need to create some AccuRev users. In this example, we’ll assume that you’re already using LDAP for other applications, and therefore user entries already exist in the LDAP server. A typical user in an LDAP server might look like this in LDIF format:

dn: cn=James T. Kirk,o=engineering,dc=enterprise,dc=com
objectclass: top
objectclass: person
objectclass: inetOrgPerson
objectclass: organizationalPerson
cn: James T. Kirk
sn: jtkirk
mail: jtkirk@enterprise.com
userPassword: jtkirk

Well, typical if they happen to be the captain of the most famous starship ever! But I digress.

In AccuRev, we need to decide how this user will be represented. In this example, we’ll use the LDAP ‘commonName’ attribute, which is shown above as ‘cn’, as the AccuRev username. Here’s the command we’ll use to create that user in AccuRev:

accurev mkuser “James T. Kirk”

At this point, we have a user represented in LDAP, and that same user represented in AccuRev. All we need to do is to tell the AccuRev server how to authenticate this user via LDAP. We do this via an AccuRev trigger known as the ’server_auth_trig’. Here is some sample code for a server_auth_trig that does just that:

use Net::LDAP;
use Net::LDAP::Util qw(ldap_error_text);
use Net::LDAP::Constant qw(LDAP_SUCCESS
            LDAP_CONNECT_ERROR
         );

use XML::Simple;
use strict 'vars';

# Server info for contacting LDAP
my $LDAP_HOST = "localhost" ;
my $LDAP_PORT = "389" ;

# We explicitly list the subtree DN to use when rewriting the incoming username as an LDAP Bind DN.
my $ldap_baseDN = "o=engineering,dc=enterprise,dc=com" ;

# Default attribute name for binding.  This attribute is concatenated
# with the incoming username and the ldap_baseDN above to form
# a Bind DN.
my $ldap_bind_attribute = "cn" ;

sub main
{
    my ($xmlinput);
    my ($command, $ip );
    my ($username, $password );
    my ($result);

    # populate array using XML::Simple routine, reading from stdin
    $xmlinput = XMLin('-', forcearray => 1, suppressempty => '');

    # set variables
    $command = $$xmlinput{'command'}[0];
    $ip = $$xmlinput{'ip'}[0];
    $username = $$xmlinput{'username'}[0];
    $password = $$xmlinput{'password'}[0];

    # First, establish a connection to the LDAP server
    my $LDAP = Net::LDAP->new($LDAP_HOST, port => $LDAP_PORT) ;
    unless ($LDAP) {
                print "Unable to connect to LDAP server on host $LDAP_HOST at port $LDAP_PORT.\n" ;
                return LDAP_CONNECT_ERROR;
    }

    # Now that we are connected, rewrite the username as a DN and attempt to bind to the server
    my $ldap_bindDN = $ldap_bind_attribute . "=" .$username . "," . $ldap_baseDN;
    print "Attempting to bind as: $ldap_bindDN\n" ;

    my $mesg = $LDAP->bind($ldap_bindDN, password => $password) ;

    # 'code' method contains any error code from the bind call
    # including success, so we return it to the caller
    my $return_code = $mesg->code;
    print "LDAP_BIND returned: $return_code\n";

    # Now unbind to free the connection
    $LDAP->unbind;

    # return the auth code to the AccuRev server
    exit ($return_code);

}

# run main routine
&main();

The main trick is to ‘rewrite’ the incoming user name in the form of an LDAP Distinguished Name, or DN, and then to use that DN and the incoming password to bind to the LDAP server. Binding is a fancy word for logging into the server. Typically this is done by providing a DN (to uniquely identify the user) and credentials (in this case, a password).

As we said earlier, we’re using a convention in this example that the incoming user name represents the ‘commonName’, or cn, attribute of the user’s LDAP entry. We then construct a string by concatenating the cn with a hard-coded base DN, the latter representing the subtree within the LDAP server where the users exist. The resulting DN in this example is:

cn=James T. Kirk,o=engineering,dc=enterprise,dc=com

which is represented in the example as the perl variable $ldap_bindDN. If the bind is successful, the trigger returns a 0, and the user is logged into AccuRev. If the bind fails, the trigger returns a non-zero code, and the user login is rejected.

There you have it. A few simple steps and you can use the industry standard LDAP mechanism to provide authentication for your AccuRev users. LDAP is used in all sorts of enterprises, from education to technology companies to government, and so is AccuRev, so we’re glad to provide a way for our customers to use this powerful and ubiquitous authentication mechanism.