Sun Java System Identity Synchronization for Windows 6.0 Deployment Planning Guide
Periodic idsync resync Operation for Primary Installation
As Global Telco uses Identity Manager to provision users
and has not configured Identity Synchronization for Windows to synchronize the creation of new users, idsync resync must be run periodically to establish links between
recently created users. If these users are not linked, then modifications
to their passwords will not synchronize. Running a full idsync resync operation for 500 thousand users could take a few
hours because synchronization of new changes is delayed during a idsync
resync operation. It is unacceptable to have Identity Synchronization for Windows off-line
for so long, so Global Telco uses Active Directory's usnCreated attribute
to synchronize only those users that have been created recently. They use
the resync-recent.pl script given below, which is run every
hour, to synchronize users that have been created in the last three days.
This script is run over users created in the last three days instead of only
the last hour because a new employee might not have a Directory Server account
until a few days after the Active Directory account is created.
The script is run periodically with the following arguments, using cron:
resync-recent.pl ad1-us.gt.com usnCreated
-f /var/opt/SUNWisw/samples/linkusers-simple-gt.cfg
-i NEW_LINKED_USERS -b -w - -q - < /var/opt/SUNWisw/passwords
The first argument is the name of the Active Directory domain controller
that the connector communicates with, the second argument determines whether
the idsync resync command should be only run on entries
that were created recently, and the remaining arguments are passed directly
to resync. In this case, the Directory Server password is reset for all users
that are newly linked. The - value used for the two password
options directs the idsync resync command to read the values
from STDIN; it prevents passwords from appearing in the command line
and being available to anyone on the system via commands such as ps.
The configuration directory password and the configuration password are written
to /var/opt/SUNWisw/passwords, and this file is then protected
with the strictest file system permissions.
resync-recent.pl script:
#!/usr/bin/perl
# This sample script shows how to run idsync resync only on users
# that have changed recently and can be used to reduce the
# impact of running resync frequently. By default it
# only resync's users that were modified or created in
# the last three days. The script stores a daily history
# of Active Directory's highestCommittedUSN attribute.
#
# The arguments of the command are
#
# <Active Directory-domain-controller-name\>
# (usnChanged|usnCreated)
# [args-for-resync]
#
# To link users that were created recently run the command
# ad.example.com usnCreated -k -f link.cfg -q <pw\> -q <pw\>
#
# To synchronize all users that were modified recently
# ad.example.com usnChanged -q <pw\> -q <pw\>
#
# To prime the object cache for users that were modified recently
# ad.example.com usnChanged -u -q <pw\> -q <pw\>
#
# NOTE: this script is only provided as a guide.
# It must be adapted to the specific Identity
# Synchronization for Windows environment by
# changing the paths and options below as appropriate
# and adding additional error handling code.
#
my $USAGE = "USAGE: resync-recent.pl “.
“<Active Directory-domain-controller-name\> ".
"(usnChanged|usnCreated) [args-for-resync]\\n";
my $IDSYNC = "/opt/SUNWisw/bin/idsync";
my $USN_FILE = "/opt/SUNWisw/bin/usnHistory";
my $MAX_DAYS_HISTORY = 3;
|
#
# SCRIPT BEGIN
#
#
# Argument parsing
#
my $adDomainController = shift @ARGV or die "$USAGE";
my $usnSearchAttr = shift @ARGV or die "$USAGE";
$usnSearchAttr =~ /usnChanged/i or
$usnSearchAttr =~ /usnCreated/i or
die "$USAGE\\n";
my $resyncArgs = getArgsAsString(@ARGV);
#
# Read the highestCommittedUSN history and add today's
# date to it if not it's there and then write the history
# out.
#
my %usnHistory = readUsnHistory();
my $today = getCurrentDate();
if (!$usnHistory{$today}) {
$usnHistory{$today} = getHighestUsn($adDomainController);
}
writeUsnHistory(%usnHistory);
#
# Run the resync command based on the oldest usnChanged
# value in the history.
#
my $oldestUsn = getOldestUsn(%usnHistory);
my $filter = "($usnSearchAttr\>=$oldestUsn)";
my $resyncCmd = "$IDSYNC resync -a \\"$filter\\" $resyncArgs";
print "Running $resyncCmd\\n";
system($resyncCmd);
#
# SCRIPT END
#
|
#
# Return the current date as a string, e.g. 2004/03/04
#
sub getCurrentDate {
my ($day, $month, $year) = (localtime(time))[3,4,5];
$month++;
$year += 1900;
return sprintf "%d/%02d/%02d", $year, $month, $day;
}
#
# Searches the root DSE at the specified host and returns
# the highestCommittedUSN value.
#
sub getHighestUsn {
my $adHost = shift @_;
my $cmd = "ldapsearch -h $adHost -b \\"\\" -s base ".
"\\"(objectclass=*)\\" highestCommittedUSN | ".
"grep highestCommittedUSN | sed \\"s/[^0-9]//g\\"";
my $highestUsn = '$cmd';
chomp $highestUsn;
print "highestCommittedUSN at $adHost is $highestUsn.\\n";
return $highestUsn;
}
#
# Converts the command line args into a string.
#
sub getArgsAsString {
my $args = "";
for my $arg (@_) {
$args .= " \\"$arg\\"";
}
return $args;
}
#
# Returns the oldest usnChanged value from the history.
#
sub getOldestUsn {
my %usnHistory = @_;
|
my @dates = getHistoryDates(%usnHistory);
# Return the last element.
return $usnHistory{$dates[$#dates]};
}
#
# Return a sorted list of the dates in the history.
#
sub getHistoryDates {
my %history = @_;
return reverse sort(keys %usnHistory);
}
#
# Writes the most recent daily history of highestCommittedUSN.
# No more than $MAX_DAYS_HISTORY days history is recorded.
#
sub writeUsnHistory {
my %usnHistory = @_;
if (!open(OUT, "\>$USN_FILE")) {
print STDERR "Could not open $USN_FILE for writing.\\n";
return;
}
# Write the history up to the last $MAX_DAYS_HISTORY days.
my @dates = getHistoryDates(%usnHistory);
for (my $i = 0;
$i <= $#dates and $i < $MAX_DAYS_HISTORY;
$i++)
{
my $date = $dates[$i];
print OUT "$date:$usnHistory{$date}\\n";
}
close(OUT);
}
#
# Reads the daily history of highestCommittedUSN
#
|
sub readUsnHistory {
my %usnHistory = ();
if (!open(IN, "<$USN_FILE")) {
print STDERR "Could not read history from $USN_FILE.\\n";
return %usnHistory;
}
while (my $line = <IN\>) {
chomp $line;
my ($date, $usn) = split /:/, $line;
$usnHistory{$date} = $usn;
}
close(IN);
return %usnHistory
}
|
An alternative to running resync periodically is
to modify the provisioning process to set the necessary link information when
the Directory Server entry is provisioned. The process is straightforward:
-
Add the dspswuser objectclass to the user
entry.
-
Set the dspswuserlink attribute to match
the user's objectguid attribute from Active Directory.
-
Set the dspswvalidate attribute to true to force on-demand password
synchronization. This step is optional.