====== Bulk Provisioning via AD ======
Two parts - VBScript on server to generate a CSV file and copy to ZCS server. Perl script on ZCS to transform into zmprov commands
===== VBScript =====
Const ADS_SCOPE_SUBTREE = 2
Const ForReading = 1, ForWriting = 2, ForAppending = 8
'standard stuff, create objects etc
set net = wscript.createobject("wscript.network")
set fso = wscript.createobject("scripting.filesystemobject")
Set shell = wscript.createobject("wscript.shell")
'AD objects for locations
Set adcnx = createobject("ADODB.Connection")
Set adcmd = createobject("ADODB.Command")
' Init AD stuff for locations
adcnx.Provider = "ADsDSOObject"
adcnx.Open "Active Directory Provider"
adcmd.ActiveConnection = adcnx
' File to write to
strCSVFile = shell.CurrentDirectory & "\users.csv"
' Query AD string - get users
adcmd.CommandText = _
"SELECT name, description, canonicalName, displayName, givenName, sn, sAMAccountName, userAccountControl, mail, distinguishedName, memberOf "_
& "FROM 'LDAP://OU=BBS,OU=Establishments,DC=BBARRINGTON,DC=internal' " _
& "WHERE objectClass='user' AND objectClass<>'computer'" _
& "ORDER BY Name"
' Properties for AD command
adcmd.Properties("Page Size") = 9999
adcmd.Properties("Timeout") = 10
adcmd.Properties("Searchscope") = ADS_SCOPE_SUBTREE
adcmd.Properties("Cache Results") = False
' Open file to write to
set fUsers = fso.OpenTextFile(strCSVFile, ForWriting, True, TristateFalse )
' Create recordset to iterate through locations
Set rstUsers = adcmd.Execute
rstUsers.MoveFirst
i=0
Do Until rstUsers.EOF
' Get attributes
strName = lcase(rstUsers.Fields("Name").Value)
arrDesc = rstUsers.Fields("description").Value
strDisplay = rstUsers.Fields("displayName").Value
strFirst = rstUsers.Fields("givenName").Value
strLast = rstUsers.Fields("sn").Value
strSAMAcctName = rstUsers.Fields("sAMAccountName").Value
strUserAcctCtl = rstUsers.Fields("userAccountControl").Value
strEmail = rstUsers.Fields("mail").Value
strDN = rstUsers.Fields("distinguishedName").Value
arrMemberOf = rstUsers.Fields("memberOf").Value
'msgbox strname, vbinformation, struseracctctl
' Find out if user is disabled or not
Select Case strUserAcctCtl
Case "544"
strStatus = "active"
Case "546"
strStatus = "locked"
End Select
' Get description
For Each strValue In arrDesc
strDesc = trim(strValue)
Next
' See which COS we need to apply
strCOS = "null"
Select Case strDesc
Case "Admin User", _
"Deputy Head Teacher", _
"Head Teacher", _
"Non-Teaching Staff User", _
"Student Teacher", _
"Support Staff User", _
"Support Staff Users", _
"System Administrator User", _
"Teaching Staff User"
strCOS = "bbstaff"
Case "Student User"
strCOS = "bbstudent"
End Select
' Now the distribution lists we belong to (big'un!)
strLists = vbNullString
' Check user is active
If strStatus = "active" AND strCos = "bbstaff" Then
' Get all groups they are a member of
For Each strGroupDN in arrMemberOf
strList = ""
' Get just the first part of the distinguished name of the group
arrGroupName = split(strGroupDN, ",")
strGroupName = arrGroupName(0)
strGroupName = Replace(strGroupName, "CN=", "")
Select Case strGroupName
Case "BBS Non-Teaching Staff", "BBS Admin Users", "Domain Admins"
strList = "supportstaff"
Case "BBS Teaching Staff"
strList = "teachers"
Case "BBS Art Teachers"
strList = "art"
Case "BBS English Teachers"
strList = "english"
Case "BBS History Teachers"
strList = "history"
Case "BBS ICT Teachers"
strList = "ict"
Case "BBS Maths Teachers"
strList = "maths"
Case "BBS MFL Teachers"
strList = "mfl"
Case "BBS Music Teachers"
strList = "music"
Case "BBS PE Teachers" ', "CN=BBS Physical Education Teachers"
strList = "pe"
Case "BBS RE Teachers" ', "CN=BBS Religious Education Teachers"
strList = "re"
Case "BBS Science Teachers"
strList = "science"
Case "BBS Teaching Staff"
strList = "teachers"
Case "BBS Technology Teachers"
strList = "technology"
End Select
if(len(strList)>0) Then strLists = strLists & strList & ":"
'msgbox strgroupdn & vbcrlf & vbcrlf & strLists, vbinformation, strname
Next
strLists = strLists & "staff"
'msgbox strLists, vbinformation, strname
End If
' Now check user's "mail" property is set. If not, set it.
' If we have a COS and No email specified
If (IsNull(strEmail)) AND (strCos <> "null") Then
' Set email!
strEmail = strName & "@bishopbarrington.net"
set objUser = GetObject("LDAP://" & strDN)
objUser.Put "mail", strEmail
objUser.SetInfo
set objUser = Nothing
End If
' Define string
' CSV Fields: username,displayname,firstname,lastname,cosname,status
strUser = strName & "," & strDisplay & "," & strFirst & "," & strLast & "," & strCOS & "," & strLists & "," & strStatus
' Write to log file
if(strCos <> "null") Then fUsers.WriteLine strUser
' Clear variables
strName = vbNullString
strDescription = vbNullString
strDisplay = vbNullString
strSAMAcctName = vbNullString
strUserAcctCtl = vbNullString
strUser = vbNullString
' Carry on
rstUsers.MoveNext
i=i+1
Loop
'msgbox "done"
' Copy file to zimbra server using PSCP (PuTTY SCP)
strCmd = "cmd /c " & shell.CurrentDirectory & "\pscp.exe -batch -pw PASS " & strCSVFile & " USER@mail.bbs.uhp.me.uk:/tmp/adusers.csv"
shell.run strCmd, 0
===== Perl =====
**/usr/local/sbin/zmadimport.pl**
#!/usr/bin/perl -w
#use strict;
use Fcntl;
# Find out how long the script takes to run
system("echo start > /tmp/zmad-start");
# Variables
my $zimbra_home = "/opt/zimbra";
my $filein = "/tmp/adusers.csv";
my $fileout = "/tmp/adusers.zmp";
my $accts = "/tmp/accts";
my $domain = "bbs.uhp.me.uk";
my $md5file = "/tmp/adusers.csv.last.md5";
# Check MD5
my $md5new = `md5sum $filein`;
my $md5last = `cat $md5file`;
#print "New CSV: $md5new";
#print "Old CSV: $md5last";
#print "\n";
if($md5new eq $md5last){ print "File not changed.\n"; exit(0); }
# Get the COS IDs from zimbra
#
my %cosids = (
"bbstaff" => getCosId("bbstaff"),
"bbstudent" => getCosId("bbstudent"),
);
# FUNCTION getCosId
# gets the cos id by running zmprov
#
sub getCosId {
my $cosname = $_[0];
my $cosid = `zmprov gc $cosname |grep zimbraId:`;
$cosid =~ s/zimbraId:\s*|\s*$//g;
return $cosid;
}
#####
# MAIN STUFF HERE
# Get all current accounts
#system("zmprov gaa > $accts");
$accts = `zmprov gaa`;
# Initialise files
open(CSV, $filein);
open(ZMP, ">$fileout");
my $csv = ;
# Parse CSV file
while($csv) {
my ($username,$displayname,$firstname,$lastname,$cosname,$lists,$status) = split(/\,/, $csv);
#$lists =~ s/\n//;
my @dists = split(':',$lists);
#print(" - $username\n");
#foreach $dist(@dists){
#print " - $dist";
#}
$displayname =~ s/\s+/ /;
$displayname =~ s/\./ /;
my $email = "$username\@$domain";
my $cosid = $cosids{$cosname};
# Check account exists
my $exists = $accts;
if($exists =~ m/$username\@$domain/){
#print " - EXISTS!";
$acctexists = 1;
} else {
$acctexists = 0;
}
print "\n";
# Write to ZMPROV file!
if($acctexists == 0){
# New accounts only
printf ZMP qq{ca $email ''\n};
printf ZMP qq{ma $email zimbraCOSid "$cosid"\n};
printf ZMP qq{ma $email cn "$username"\n};
}
# Update existing accounts!
# - Name
if($firstname ne ""){ printf ZMP qq{ma $email givenName "$firstname"\n}; }
if($lastname ne ""){ printf ZMP qq{ma $email sn "$lastname"\n}; }
if($displayname ne ""){ printf ZMP qq{ma $email displayName "$displayname"\n}; }
# - Description field
my $desc = "";
if($cosname eq "bbstaff"){ $desc = "Staff Account"; }
if($cosname eq "bbstudent"){ $desc = "Student Account"; }
printf ZMP qq{ma $email description "$desc"\n};
# - Account status
printf ZMP qq{ma $email zimbraAccountStatus $status\n};
# Distribution lists
if(scalar(@dists)>1){
foreach $list(@dists){
printf ZMP qq{adlm $list\@$domain $email\n};
}
}
# - END
printf ZMP qq{\n};
# next line
$csv = ;
}
# Close text files
close(CSV);
close(ZMP);
# Now import the file
system("zmprov --verbose --file=$fileout");
# Hash the file to compare on the next run
system("md5sum $filein > $md5file");
# END MAIN STUFF
#####
# To find out how long the script takes
system("echo end > /tmp/zmad-end");