Table of Contents

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 = <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 = <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");