One of the downfalls of Zimbra is its poor integration with Active Directory, at least for the OSS version. This can be solved though with some scripting.
The basis of this script comes from “Zimbra autocreate accounts with Active Directory or LDAP” which was a good start for me but was much more complicated than I needed.
The purpose of this document is to document the method that I used to dynamically update the distribution lists from the OU membership on our Active Directory Server.
Assumptions of this Document
I am using:
- Ubuntu Server 12.04 LTS
- Zimbra version 8.0 OSS Version
- Python
- Microsoft Active on Windows 2008 Server R2
Modify / Create the Distribution Group and Add Members from AD
First thing is to create the script that gets a list of the users from AD and creates the necessary groups. A word of caution here is that you need to be careful of the indentation in Python. If the indentation of the lines is wrong (not what I have here) the script won’t work.
The values in RED should be changed to match your site.
$ sudo mkdir /opt/import $ cd /opt/import $ sudo vi groups.py
#!/usr/bin/python import ldap,sys,os,time # Address of LDAP Server ldapHost = "ldap://adServer.domain.local:389" #DN and Password of user to bind to AD with user = "CN=UserName,CN=Users,DC=domain,DC=local" password = "PASSWORD" fqdn = "mailhost.domain.local" # FQDN of Zimbra Domain Configured filter = "sn=*" pathtozmprov="/opt/zimbra/bin/zmprov" #--------------END VAR-------------------- groupName = str(sys.argv[1]) baseDN = str(sys.argv[2]) f = os.popen(pathtozmprov +' -l gaa ') zmprovgaa = [] zmprovgaa = f.readlines() try: l = ldap.initialize(ldapHost) l.simple_bind_s(user, password) result = l.search_s(baseDN, ldap.SCOPE_SUBTREE,filter) delete_group = pathtozmprov + " ddl " + groupName + "@" + fqdn create_group = pathtozmprov + " cdl " + groupName + "@" + fqdn populate_group = pathtozmprov + " adlm " + groupName + "@" + fqdn for (dn, vals) in result: try: mail = vals['mail'][0] except: mail = vals['sAMAccountName'][0].lower() + "@" + fqdn sys.stdout.flush() populate_group = populate_group + " " + mail os.system (delete_group) os.system (create_group) os.system (populate_group) except ldap.LDAPError, error_message: print error_message l.unbind_s()
$ sudo chmod 755 groups.py
Example usage:
$ sudo su zimbra -
$ cd /opt/import
$./groups.py staff "OU=Staff,OU=Users,DC=domain,DC=local"
Specifically, this will create a Distribution List with the name of “staff” which contains all of the users in the OU listed. It’s assumed that you will already have the users created in Zimbra. The script to do this will be documented soon. If you need it now, you can email me antony@street.id.au.
Finishing Up
You could call groups.py directly from cron but it’s better to create a shell script to call it and then add the shell script to cron. This way you can easily add and edit the required OUs.
$ sudo vi batch_groups.sh
#!/bin/bash
/opt/import/groups.py staff "OU=Staff,OU=Users,DC=domain,DC=local"
Finally we’ll schedule the command to run by adding it to crontab. To complete this:
$ sudo su zimbra - $ crontab -e
Insert the following line at the beginning of the file.
@daily /opt/import/batch_groups.sh
This script looks good, but I’d rather find a way to import the members of an Active Directory Group into a Zimbra distribution list. Unfortunately, I don’t have the python or ldap skills to make the necessary modifications. Do you know how to do it?
Found a python script that synchronizes AD groups with Zimbra distribution lists. In our environment, it needed a couple changes, but it seems to work.
https://www.zimbra.com/forums/administrators/63065-how-syncronizing-distribution-lists-ad-groups.html
Thank you for sharing the link. In our environment we have the users (students) in a very structured GPO hierarchy. I can see why that might not work in other environments. I hope it works well for you
Hi,
I have edited your script for take a Distribution Group and replicate it in Zimbra. This script read members of a AD distribution Gruop and recreate as a Distribution List with same members in Zimbra.
You mas invoke it like:
python populate_distributionlist_AD.py GROUP_NAME “cn=GROUP_NAME,ou=Grupos,ou=Folder1,dc=domain,dc=com”
Where GROUP_NAME is a group in your AD:
#!/usr/bin/python
import ldap,sys,os,time
# Address of LDAP Server
ldapHost = “ldap://YOUR_SERVER:389”
#DN and Password of user to bind to AD with
user = “CN=Administrador,CN=Users,DC=domain,DC=com”
password = “XXXXXXX”
fqdn = “domain.com” # FQDN of Zimbra Domain Configured
filter = “sn=*”
pathtozmprov=”/opt/zimbra/bin/zmprov”
#————–END VAR——————–
groupName = str(sys.argv[1])
baseDN = str(sys.argv[2])
f = os.popen(pathtozmprov +’ -l gaa ‘)
zmprovgaa = []
zmprovgaa = f.readlines()
try:
l = ldap.initialize(ldapHost)
l.simple_bind_s(user, password)
result = l.search_s(baseDN, ldap.SCOPE_SUBTREE,”cn=*”)
delete_group = pathtozmprov + ” ddl ” + groupName + “@” + fqdn
create_group = pathtozmprov + ” cdl ” + groupName + “@” + fqdn
populate_group = pathtozmprov + ” adlm ” + groupName + “@” + fqdn
for resultado in result:
result_dn = resultado[0]
result_attrs = resultado[1]
for member in result_attrs[“member”]:
result2 = l.search_s(member, ldap.SCOPE_SUBTREE,”cn=*”,[‘mail’])
populate_group = populate_group + ” ” + str(result2).split(‘:’,2)[1][3:-5]
sys.stdout.flush()
os.system (delete_group)
print(delete_group)
os.system (create_group)
print(create_group)
os.system (populate_group)
print(populate_group)
except ldap.LDAPError, error_message:
print error_message
l.unbind_s()
Thanks man!
This was exactly what I was looking for: you saved me a lot of time. works like a charm!
Looks like not hard
Hi..
Friend,
How can I search in groups that contain spaces?
Eg cn = Enterprise IT