Zimbra offers Open Source email server software and shared calendar for Linux and the Mac
 
Go Back   Zimbra - Forums > Zimbra Collaboration Suite > Administrators

Welcome to the Zimbra - Forums!
Welcome, if you would like to post a comment please register. We also encourage you to explore all things Zimbra with our team and members of the community.

Reply
 
LinkBack Thread Tools Display Modes
  #1 (permalink)  
Old 10-06-2008, 07:11 AM
Active Member
 
Posts: 27
Lightbulb Active Directory Script to import users to Zimbra

Hi, guys.

I'm working on a simple script that creates zimbra user accounts as I create them in my w2k AD server (via crontab). It also deletes zmibra accounts when no longer exist in my AD.

This is the first try (unstable, untested, unsecure) but wanted to share with you, maybe someone can help me to make it better.

The idea is simple: it makes a list of AD users via ldapsearch, then makes a list of ZCS users via zmprov and finally makes a diff between both to find different entries. Take a loot at it and tel me what do you think.

ToDo list:
- add an option to make it quiet to be run from crontab
- add an option to make it verbose so it can be debugged
- add an option to generate a log!

Code:
#!/bin/bash
# zsync_ad.sh is a script thant syncs AD users and Zimbra users
# It is unidirectional, just replicates changes from AD to ZCS
# Developed on by Eduardo Gonzalez <egrueda at gmail dot com> 
# Testing version 0.6 - Use at your own risk

LDAPSEARCH=/usr/bin/ldapsearch
ZMPROV=/opt/zimbra/bin/zmprov
DOMAIN_NAME="example.com"
TIMESTAMP=`date +%N`
TMP_DIR=/tmp
ADS_TMP=$TMP_DIR/users_ads_$TIMESTAMP.lst
ZCS_TMP=$TMP_DIR/users_zcs_$TIMESTAMP.lst
DIF_TMP=$TMP_DIR/users_dif_$TIMESTAMP.lst

# Server values
LDAP_SERVER="ldap://111.1.1.150"
BASEDN="dc=example,dc=com"
BINDDN="CN=username,DC=example,DC=com"
BINDPW="secret"
FILTER="(&(sAMAccountName=*)(objectClass=user)(givenName=*))"
FIELDS="mail"

# Extract users from ADS
echo -n "Quering ADS... "
$LDAPSEARCH -x -H $LDAP_SERVER -b $BASEDN -D "$BINDDN" -w $BINDPW "$FILTER" $FIELDS | \
  grep "@$DOMAIN_NAME" | \
  awk '{print $2}' | \
  sort > $ADS_TMP
echo "Found `cat $ADS_TMP | wc -l` users ($ADS_TMP)"

# Extract users from ZCS
echo -n "Quering ZCS... "
$ZMPROV gaa $DOMAIN_NAME > $ZCS_TMP
echo "Found `cat $ZCS_TMP | wc -l` users ($ZCS_TMP)"

# Generate diff
echo "Generating diff file ($DIF_TMP)"
diff -u $ZCS_TMP $ADS_TMP | grep "$DOMAIN_NAME" > $DIF_TMP

# Clean up users list
rm -f $ADS_TMP $ZCS_TMP

# Import new users
echo -n "New users: "
cat $DIF_TMP | grep ^+ | wc -l
for i in $(cat $DIF_TMP | grep ^+ | sed s/^+//g);
do
  echo -n " - Adding $i ";
  $ZMPROV createAccount $i passwd > /dev/null;
  RES=$?
  if [ "$RES" == "0" ]; then echo "[Ok]"; else echo "[Err]"; fi
done

# Delete old users
echo -n "Old users: "
cat $DIF_TMP | grep ^- | wc -l
for i in $(cat $DIF_TMP | grep ^- | sed s/^-//g);
do
  echo -n " - Deleting $i ";
  $ZMPROV deleteAccount $i > /dev/null;
  RES=$?
  if [ "$RES" == "0" ]; then echo "[Ok]"; else echo "[Err]"; fi
done


# Clean up diff list
rm -f $DIF_TMP
Cheers
Reply With Quote
  #2 (permalink)  
Old 02-25-2009, 02:15 PM
Intermediate Member
 
Posts: 19
Default

Hi!



I've been trying your script, and it works fine (good work!). However, I 'd want to ask you if is it possible to retrieve more attributes from AD to insert in zimbra-ldap, such as user name, surname, telephone number, etc (not only e-mail address). In case it is possible... do you have any clue?



Thanks a lot



P.S. I speak Spanish too
Reply With Quote
  #3 (permalink)  
Old 02-25-2009, 02:40 PM
Active Member
 
Posts: 27
Default

I'm glad to hear that :-)
Yes, check the line, around line 22, which says:
Code:
FIELDS="mail"
I'm only reading "mail" field, but you can read whatever attribute you have, it's just an ldap query
You will also need to change the "$ZMPROV createAccount" line so it can use the attributes you're reading.

Gracias por tu post :-)
Reply With Quote
  #4 (permalink)  
Old 02-25-2009, 02:51 PM
Intermediate Member
 
Posts: 19
Default

Uhm.. I was playing with that line today (perhaps wrong), and changed it this way:

FIELDS="mail givenName sn telephonenumber"

but no luck, it returned only mail field.

Well, knowing it's possible, I suppose the best thing I can do is reading about the syntax, modifying the script and trying it more deeply ( I can't now).

Thanks a lot again!

Siempre es reconfortante que el mejor script que haya visto sobre el tema sea made in spain, jejeje (o en país hispanoparlante, vaya) Al fin algo útil!

Last edited by milesteg : 02-25-2009 at 02:57 PM.
Reply With Quote
  #5 (permalink)  
Old 02-25-2009, 10:28 PM
Active Member
 
Posts: 27
Default

Oops, I forgot: there's a filter for the ldat query output so I was only taken the email. Check the query:
Code:
$LDAPSEARCH -x -H $LDAP_SERVER -b $BASEDN -D "$BINDDN" -w $BINDPW "$FILTER" $FIELDS | \
  grep "@$DOMAIN_NAME" | \
  awk '{print $2}' | \
  sort > $ADS_TMP
As you see, I'm doing a grep for the domain name and then an awk to read only the second column.
So it will be necesary to change that grep into grep -e attr -e attr and maybe remove or adjust the awk line.
Also I see that more changes must be done, since my original idea was to make a diff between two sorted email lists, but now one of those list will have more fields.
Maybe to simplify the script should create 2 output files, one with just the email, to make the diff, and other one with the attributes, which can be grep-ed on real time just before zmprov command.

Hey! This mod sounds quite interesting, as it will make a powerful script. Think I'm gonna work on it. I will also add a previous modification I made in a recent zimbra installation so that the script checks the availability of both ldap servers to make sure they're online.

I hope I can give you more details tomorrow, as today I'll be in an in-situ installation.

P.D. Y aqui tienes a dos españoles hablando en inglés entre ellos. Maldita globalizacion... Saludos desde Madrid.
Reply With Quote
  #6 (permalink)  
Old 03-20-2009, 04:00 AM
Starter Member
 
Posts: 2
Talking sample script auto syncronize ad user

#!/bin/bash
# zsync_ad.sh is a script thant syncs AD users and Zimbra users

LDAPSEARCH=/usr/bin/ldapsearch
ZMPROV=/opt/zimbra/bin/zmprov
DOMAIN_NAME="nuclearmalaysia.gov.my"
TIMESTAMP=`date +%N`
TMP_DIR=/tmp
ADS_TMP=$TMP_DIR/users_ads_$TIMESTAMP.lst
ZCS_TMP=$TMP_DIR/users_zcs_$TIMESTAMP.lst
DIF_TMP=$TMP_DIR/users_dif_$TIMESTAMP.lst

# Server values
LDAP_SERVER="ldap://192.168.46.129"
BASEDN="DC=nuclearmalaysia,DC=gov,DC=my"
BINDDN="CN=ldapbind,DC=nuclearmalaysia,DC=gov,DC=m y"
BINDPW="password"
FILTER="(&(sAMAccountName=*)(objectClass=user)(giv enName=*))"
FIELDS="mail displayName"

# Extract users from ADS
echo -n "Quering ADS... "
$LDAPSEARCH -x -H $LDAP_SERVER -b $BASEDN -D "$BINDDN" -w $BINDPW "$FILTER" $FIELDS | \
grep "@$DOMAIN_NAME" | \
awk '{print $2}' | \
sort > $ADS_TMP
echo "Found `cat $ADS_TMP | wc -l` users ($ADS_TMP)"

# Extract users from ZCS
echo -n "Quering ZCS... "
$ZMPROV gaa $DOMAIN_NAME > $ZCS_TMP
echo "Found `cat $ZCS_TMP | wc -l` users ($ZCS_TMP)"

# Generate diff
echo "Generating diff file ($DIF_TMP)"
diff -u $ZCS_TMP $ADS_TMP | grep "$DOMAIN_NAME" > $DIF_TMP

# Clean up users list
# rm -f $ADS_TMP $ZCS_TMP

# Import new users
echo -n "New users: "
cat $DIF_TMP | grep ^+ | wc -l
for i in $(cat $DIF_TMP | grep ^+ | sed s/^+//g);
do
echo -n " - Adding $i ";
display_name=`$LDAPSEARCH -x -H $LDAP_SERVER -b $BASEDN -D "$BINDDN" -w $BINDPW mail=$i displayName | \
grep "displayName:" | awk -F: '{print $2}'`
echo $i"|"$display_name
$ZMPROV createAccount $i passwd displayName "$display_name" > /dev/null;
RES=$?
if [ "$RES" == "0" ]; then echo "[Ok]"; else echo "[Err]"; fi
done

# Delete old users
# echo -n "Old users: "
# cat $DIF_TMP | grep ^- | wc -l
# for i in $(cat $DIF_TMP | grep ^- | sed s/^-//g);
# do
# echo -n " - Deleting $i ";
# $ZMPROV deleteAccount $i > /dev/null;
# RES=$?
# if [ "$RES" == "0" ]; then echo "[Ok]"; else echo "[Err]"; fi
# done


# Clean up diff list
# rm -f $DIF_TMP
Reply With Quote
  #7 (permalink)  
Old 07-07-2009, 09:58 AM
Junior Member
 
Posts: 7
Default Active Directory Script to import users to Zimbra

Hello

Well I thought I would post a script that I have done to get users into Zimbra from Active Directory.

I copied parts from zsync_ad.sh script by Eduardo Gonzalez.

But i needed more info from the AD to get into each Zimbra account.

So its still a little ruff around the edges and i will post a cleaner (so dont point out the terrible use of awk ) copy as soon as i get around to it.

But essentially it check the AD for a list of users and compares it against Zimbra's users using LDAPSEARCH and adds each NEW user into Zimbra.

Code:
#!/bin/bash

# Zimbra to Active Directory By Dominic Carpenter but concept and parts copied from zsync_ad.sh script by Eduardo Gonzalez so a big thank you to him
# LDAP Search on Active Directory and Zimbra with a sort and strip. 
# This does not modify data lready in Zimbra, it only creates if the account is new to zimbra
# To Change the Active Directory search limit (1000) http://www.nordicedge.se/support/kb/questions/236/NSD1122+How+to+change+the+LDAP+search+limit+limitation+of+1000+objects+in+AD+LDS

Domain="YOURDOMAIN.COM" # DNS Name or IP of Active Directory
ADDOMAIN="YOURDOMAIN.COM" # Active Directory Domain (No idea why I added this twice......
DN="OU=Account,DC=YOURDOMAIN,DC=COM" # Search an OU or the base DN
USER_DN="cn=Zimbra,cn=Users,DC=YOURDOMAIN,DC=COM" # Authenticated User to do search
USER_PASS="PASSWORD" # Authenticated User Password
ZM_Domain="localhost" # DNS Name or IP of Zimabra Server 
ZMProv="/opt/zimbra/bin/zmprov"
ZMServer="ZMIMBRA.YOURDOMAIN.COM" # Zimbra Server
ZMSearch="ou=people,DC=YOURDOMAIN,DC=COM" # Zimbra Search Path

printf "Looking for Users in Active Directory.... \n" 
ldapsearch -x -h $Domain -b $DN -D $USER_DN -w $USER_PASS -LLL "(mail=*)" name | grep name | sed 's/name: //g' | sort > /tmp/ADUsers.txt
ADcount=`cat /tmp/ADUsers.txt | wc -l | sed 's/^[ \t]*//'` # Count AD Users
printf "$ADcount AD Users writen to tmp file ... \n"

# Get User info from Zimbra so we can compare user lists

printf "Quering Zimbra Server... \n"
ldapsearch -h $ZMServer -x -b $ZMSearch '(objectclass=*)' displayName | grep displayName | sed 's/displayName: //g' | sort > /tmp/ZMUsers.txt
ZMcount=`cat /tmp/ZMUsers.txt | wc -l | sed 's/^[ \t]*//'` # Count ZM Users
printf "$ZMcount Zimbra Users writen to tmp file ... \n"

# Generate diff to get unique users

printf "Generating diff file /tmp/Users.txt \n"
diff -u /tmp/ZMUsers.txt /tmp/ADUsers.txt | grep ^+ | grep -v tmp | sed 's/+//g' > /tmp/Users.txt # Clean 
rm -f /tmp/ZMUsers.txt /tmp/ZMUsers.txt

IFS="
"
# Loop through the unique users

count=`cat /tmp/Users.txt | wc -l | sed 's/^[ \t]*//'`
printf "starting process lookup on $count users... \n"
for line in `cat /tmp/Users.txt`;do

# Return the results in the following;
# Name of user that is in the loop
# Description of the User
# Strip the CN path of user to extract top OU i.e employees
# The Fax Number (used for id number)
# The email Address
# The Username
# The Telephone Number
# Full Search String returned
# Unhash to see the echo results

searchValues=`ldapsearch -x -h $Domain -b $DN -D $USER_DN -w $USER_PASS -LLL "(name=$line)" mail description telephoneNumber facsimileTelephoneNumber sAMAccountName sn givenName`
Name=`echo $line` # name of user
#Description=`echo $searchValues | grep -w description |  awk '{split ($0, a, "description:"); print a[2]}' |  awk '{split ($0, a, ":"); print a[1]}' | awk '{sub($NF,"");sub(" ","");print}'| sed 's/^[ \t]*//';exit 0` # Description
CN_path=`echo $searchValues | grep -w OU | awk '{split ($0, a, ","); print a[2]}' | sed 's/OU=//g'` # Get the Group from the OU path i.e. Employees
FAX=`echo $searchValues | grep -w facsimileTelephoneNumber: |  awk '{split ($0, a, "facsimileTelephoneNumber:"); print a[2]}' | awk '{print $1}' | sed 's/facsimileTelephoneNumber//g';exit 0` # Fax Number (Employee ID)
Email=`echo $searchValues | grep -w mail: | awk '{split ($0, a, "mail:"); print a[2]}' | sed 's/^[ \t]*//'` # email mail address
Username=`echo $searchValues | grep -w sAMAccountName: | awk '{split ($0, a, "sAMAccountName:"); print a[2]}' | awk '{print $1}'` # get the username
#Telephone=`echo $searchValues | grep -w telephoneNumber: | awk '{split ($0, a, "telephoneNumber:"); print a[2]}' | awk '{print $1}';exit 0` # the Telephone Number
SN=`echo $searchValues |  awk '{split ($0, a, "sn:"); print a[2]}' | awk '{print $1}'` # Last Name
GivenName=`echo $searchValues |  awk '{split ($0, a, "givenName:"); print a[2]}' |  awk '{split ($0, a, "sAMAccountName:"); print a[1]}' | sed 's/^[ \t]*//'` # Two splits because they might have two names (clean this messy code up.... )

Full_String=`echo $searchValues` # full string returned

#echo $Name
#echo $GivenName
#echo $SN
#echo $Description  
#echo $CN_path
#echo $FAX
#echo $Email
#echo $Username
#echo $Telephone
#echo $Full_String
#echo # Space the view results

printf "Creating User $Name \n"; # Print something so i know its doing something
#echo $ZMProv createAccount $Email pass
$ZMProv createAccount $Email passwd > /dev/null; # No Pass as authentication is from AD
$ZMProv modifyAccount $Email displayName "$Name"; # Display Name
$ZMProv modifyAccount $Email givenName "$GivenName"; # Last Name 
$ZMProv modifyAccount $Email sn "$SN"; # First Name(s)
$ZMProv SetAccountCOS $Email $CN_path; # Set COS based apon the OU that the user sits in. i.e CN=My Name,OU=GroupOU,OU=stuff,DC=Domain,DC=Com the COS is GroupOU and is pre-created in Zimbra
#$ZMProv modifyAccount $Email description $Description; 
#$ZMProv modifyAccount $Email Notes $FAX; # <---- check LDAP Schema as this is not working.....
$ZMProv AddAccountAlias $Email $Username"@"$ADDOMAIN; # Account Alias based apon there sAMAccountName 
/opt/zimbra/bin/zmmailbox -z -m $Email cf -u 'http://url-to-my-rss-feed/rss.xml' /folder-for-rss-feed # Add RSS Feed to each user
# $ZMProv modifyAccount $Email telephoneNumber $Telephone
# $ZMProv modifyAccount $Email zimbraAccountStatus maintenance # Used for testing so search can locate and delete
# $ZMProv modifyAccount $Email zimbraAccountStatus active,maintenance,locked,closed # Edit for correct Account Status


done

Last edited by Guest : 07-07-2009 at 10:00 AM.
Reply With Quote
  #8 (permalink)  
Old 07-07-2009, 02:02 PM
Starter Member
 
Posts: 1
Default deltas on my version of zsync_ad.sh

hi forum !

i'm getting approches with zimbra...i was get into a rut ...in this step...an some days ago i found the "zsync_ad.sh" script...very usefull but it doesn't works for me .. so i made a (really) little changes...and they are here ...

Code:
FILTER="-f /path/to/your/ldapfilterfile/fileWithOneFilterPerLine.ldap"

$LDAPSEARCH -x -H $LDAP_SERVER -b $BASEDN -D "$BINDDN" -w $BINDPW  $FILTER $FIELDS | \

i post only the deltas...the rest are the same ...and obviously the "fileWithOneFilterPerLine.ldap"

here is:
Code:
(|(&(objectCategory=person)(objectSid=*)(!samAccountType:1.2.840.113556.1.4.804:=3))(&(objectCategory=person)(!objectSid=*))(&(objectCategory=group)(groupType:1.2.840.113556.1.4.804:=14)))
this filter it was shamesly stolen from ZCS Migration Wizard , [Query Builder]

i hope it be usefull for somebody

cheers and happy Zincronize!! ...
Reply With Quote
  #9 (permalink)  
Old 08-17-2009, 07:57 PM
Special Member
 
Posts: 145
Default

Umh, I like I can enter domain name, ldap server address, basedn, username and password by hand so, I modified some source code like here:
Quote:
echo: "Domain name:"
read DOMAIN_NAME
echo "Address of AD server:"
read LDAP_SERVER
echo " Enter baseDN:"
read BASEDN echo "
username:"
read USERNAME
echo " password:"
read PASSWORD

Last edited by dalmate : 08-17-2009 at 08:03 PM.
Reply With Quote
  #10 (permalink)  
Old 08-18-2009, 12:53 AM
Junior Member
 
Posts: 7
Default

Maybe someone could find this useful. I wrote a python script to do that, but instead of deleting account I put it into closed state in order to be able to perform archival steps prior to removal but also to protect account from bugs that could cause it to be removed (loosing all the mails) while in fact it is still active.

In the course of this, I also wrote Python class to handle Zimbra administration connections that wraps SOAP messages. It's not finished as I don't have time now, but if anyone is interested the code can be found here:

Stjepan Groš - Homepage

S
__________________
------------------------------------------------
http://www.zemris.fer.hr/~sgros
Reply With Quote
Reply


Thread Tools
Display Modes


Similar Threads

Why Join?

Registering let's you ask questions, makes it easier to search, displays any files attached to posts, and notifies you about replies.

Zimbrablog.com




 

Search Engine Optimization by vBSEO 3.1.0