Active Directory Name to Distinguished Name Conversion

This note demonstrates some exciting Perl magic. It presents several ways to convert a directory-like name of an object in Active Directory to a X.500 Distonguished name.

The script is interrupted by useful comments explaining the following chunk.

#!/usr/bin/perl

use strict;
use warnings;
use locale;
use English;

my $user = 'userName@sub.domain.de/ou 1/ou2';

The following code chunk demonstrates how to perform the conversion in two lines. Unfortunately, this is rather hard to read.

print "n";
{
    print 'line ' . __LINE__ . ': ' . $user . "n";
    my ($userName, $dnsDomain, $ou)
        = ($user =~ m!^([^@]+)@([^/]+)/(.+)$!);
    my $ldap = 'cn=' . $userName
             . ',ou=' . join(',ou=', reverse split('/', $ou))
             . ',dc=' . join(',dc=', split('.', $dnsDomain));
    print 'line ' . __LINE__ . ': ' . $ldap . "n";
}

This three-liner makes the conversion rather easy to understand after several months.

print "n";
{
    print 'line ' . __LINE__ . ': ' . $user . "n";
    my ($userName, $dnsDomain, @ou) = split(m![@/]!, $user);
    $dnsDomain =~ s!.!,dc=!g;
    my $ldap = 'cn=' . $userName
             . ',ou=' . join(',ou=', reverse @ou)
             . ',dc=' . $dnsDomain;
    print 'line ' . __LINE__ . ': ' . $ldap . "n";
}

Although the following chunk consist of several lines, it contains a single regular expression performing the conversion. To run it using strict, you need to declare $ldap.

print "n";
{
    my $ldap;
    print 'line ' . __LINE__ . ': ' . $user . "n";
    $user =~ m!
        ([^@]+)@                          # matches the common name
        (.?                              # matches individual
            ([^./]+)                     # domain components
            (?{$ldap.=',dc='.$^N})        # and appends them
        )+
        (/                                # matches individual
            ([^/]+)                       # ou components
            (?{$ldap=',ou='.$^N.$ldap})   # and prepends them
        )*
        (?{$ldap='cn='.$1.$ldap})         # prepends the common name
    !x;
    print 'line ' . __LINE__ . ': ' . $ldap . "n";
}
Feedback is always welcome! If you'd like to get in touch with me concerning the contents of this article, please use Twitter.