Sun Java System Identity Synchronization for Windows 6.0 Deployment Planning Guide

Unlinking Migrated Windows NT Entries

To unlink migrated users, the dspswuserlink attribute is removed from each Directory Server entry that is affected. The following sample script can be used to remove this attribute from a large number of users. The script accepts ldapsearch arguments for the users that should be unlinked.

#! /usr/bin/perl
# This script is used to break the link between Directory Server
# entries and the corresponding Windows entries.  Provide
# complete ldapsearch arguments for the users to unlink.
# If many users are unlinked, use -D "cn=Directory Manager" to
# avoid search results limits imposed by the directory server.
# ldapsearch and ldapmodify must be in the path, and the
# current directory must be writable.
#
# Modify these variables to point to the ldapsearch and
# ldapmodify commands that ship with the Sun Directory Server.
# The versions that ship with Solaris will not work in this script.
die "Edit this script to modify these variables and then remove this
line.\\n";
my $LDAPSEARCH_EXE = "/opt/mps/serverroot/shared/bin/ldapsearch";
my $LDAPMODIFY_EXE = "/opt/mps/serverroot/shared/bin/ldapmodify";
my $USAGE = "Usage: unlink.pl <ldapsearch args for users to unlink\>\\n";
# Valid ldapsearch options that don’t apply to ldapmodify
my %INVALID_LDAPMODIFY_OPTS = ("-b" =\> 1, "-s" =\> 1);
# Valid ldapsearch options that have arguments and don’t apply
# to ldapmodify
my %INVALID_LDAPMODIFY_OPTS_WITH_ARG = ("-b" =\> 1, "-s" =\> 1);
# The file name for the file to hold the unlink ldif
my $UNLINK_LDIF_FILE = "unlink.ldif";
#
# SCRIPT BEGIN
#
scalar(@ARGV) \> 0 or die "$USAGE";
# Run ldapsearch to find the users to unlink.
my $ldapsearchArgs = getLdapsearchArgs(@ARGV);
my $ldapsearchCmd = "$LDAPSEARCH_EXE $ldapsearchArgs";
my $matchedUsersLdif = ”$ldapsearchCmd”;
lastCommandSucceeded() or die "Failed when running “. “$ldapsearchCmd.\\n$USAGE";
# Construct ldif to unlink each matched user.
my @userDns = parseDnsFromLdif($matchedUsersLdif);
print "Matched ".scalar(@userDns)." linked entries.\\n";
my $unlinkLdif = constructUnlinkLdif(@userDns); my $fileName =
writeLdifToFile($unlinkLdif);
# Run ldapmodify to unlink the users.
my $ldapmodifyArgs = getLdapmodifyArgs($fileName, @ARGV);
my $ldapmodifyCmd = "$LDAPMODIFY_EXE $ldapmodifyArgs";
”$ldapmodifyCmd”;
print "Unlinked ".scalar(@userDns)." entries.\\n";
lastCommandSucceeded() or die "Failed when running “.  “$ldapmodifyCmd.\\n$USAGE";
exit 0;
#
# SCRIPT END
# Return true iff the last command succeeded.
#
sub lastCommandSucceeded {
    return ($? \>\> 8) == 0;
}
#
# Return the dns in the ldif.
#
sub parseDnsFromLdif { my $ldif = shift @_; my @dns = ();
# Note that DNs can span multiple lines.
while ($ldif =~ /(^dn:.*(\\n^[ ]+\\S+.*)*)/gmi) {
push @dns, $1;
}
return @dns;
}
#
# Return ldif for all users to unlink
#
sub constructUnlinkLdif {
    my $ldif = "";
    for my $dn (@_) {
        $ldif .=
            "$dn\\n" .
            "changetype: modify\\n" .
            "replace: dspswuserlink\\n" .
            "-\\n" .
            "\\n";
    }
    return $ldif;
}
#
# Writes ldif to a file and returns the name of the file.
#
sub writeLdifToFile {
    my $ldif = shift @_;
    open(LDIF, "\>$UNLINK_LDIF_FILE") or
         die "Could not open $UNLINK_LDIF_FILE for writing.\\n";
    print LDIF $ldif;
    close(LDIF);
    return $UNLINK_LDIF_FILE;
}
#
# Return the arguments to use for ldapsearch as a single string
#
sub getLdapsearchArgs {
# Always use -L because Solaris’s ldapsearch doesn’t
# return ldif by default.
my $ldapsearchArgs = "";
# Modify the last argument to include the search filter
    my $lastIndex = $#_;
    $_[$lastIndex] = getLinkedSearchFilter($_[$lastIndex]);
    for my $arg (@_) {
        $ldapsearchArgs .= " '$arg'";
    }
    return $ldapsearchArgs;
}
#
# Construct an ldapfilter that only matches linked users.
#
sub getLinkedSearchFilter {
    my $filter = shift @_;
    if (!($filter =~ /^</)) {
        $filter = "($filter)";
    }
    return "(&(dspswuserlink=*)$filter)";
}
#
# Return the arguments to use for ldapmodify as a single string.
#
sub getLdapmodifyArgs {
    my $ldifFile = shift @_;
    my $ldapmodifyArgs = "-f '$ldifFile'";
    my $prevArg = "";
    # Iterate through all args, skipping ones that don’t
    # apply and the last one.
    for my $i (0..($#_ - 1)) {
        my $arg = $_[$i];
        if (!$INVALID_LDAPMODIFY_OPTS{$arg} &&
            !$INVALID_LDAPMODIFY_OPTS_WITH_ARG{$prevArg}) {
            $ldapmodifyArgs .= " '$arg'";
        }
        $prevArg = $arg;
    }
    return $ldapmodifyArgs;
}
            

The next batch of Example Bank users to be migrated from Windows NT to Active Directory have a last name that starts with the letter G. After these users have been migrated, the following unlink.pl script is executed to unlink these entries in Directory Server.

bash-2.05# ./unlink.pl -h master-east.eb.com 
-b "dc=eb,dc=com" -D "cn=Directory Manager" 
-w <omitted password\> "(sn=G*)"
Matched 1346 linked entries.
Unlinked 1346 entries.

In this example, 1346 entries were migrated and thus unlinked. The Directory Manager dn is provided to avoid search results limits in the Directory Server. If other accounts are used, make sure that their search capabilities are not limited, to avoid unlinking only subsets of users.