1

Topic: Sync mail users with another LDAP server

======== Required information ====
- iRedMail version: 0.8.6
- Store mail accounts in which backend (LDAP/MySQL/PGSQL): OpenLDAP
- Linux/BSD distribution name and version: CentOS 6.4
- Related log if you're reporting an issue:
====

Hi !

I have in our university LDAP server with userdata for all employees and students .... Since that LDAP server is part of system which is under certification I cannot add or modify shemas and users, but I found way to sync that LDAP with LDAP from iRedMail mail server

Here is code (bash script which ADD users from Source LDAP to iRedMail LDAP, ... if user exist than only sync passwords from Source LDAP to iRedMail)

#!/bin/sh
#
# Sync users from another LDAP
#
# run in iRedMail-0.8.6/tools 
#
. ../conf/global
. ../conf/core
#
# LDAP from which users will be synced (Source LDAP) fill in your data
#
urlAAI="ldap://sourceldap:389"
basednAAI="dc=base,dc=ext"
binddnAAI="cn=admin,dc=base,dc=ext"
bindpwAAI="password"
#
# iRedMail LDAP (target LDAP) fill in your data
#
urlMAIL="ldap://targetldap:389"
basednMAIL="o=domains,dc=base,dc=ext"
binddnMAIL="cn=Manager,dc=base,dc=ext"
bindpwMAIL="password"
#
# common variables from iRedMail setup
#
STORAGE_BASE_DIRECTORY="/var/vmail/vmail1"
STORAGE_BASE="$(dirname ${STORAGE_BASE_DIRECTORY})"
STORAGE_NODE="$(basename ${STORAGE_BASE_DIRECTORY})"
#
# get users uid from Source LDAP (I here have parameter which distinguish
# different types of users(hrEduPersonPrimaryAffiliation=djelatnik) for employees in Source LDAP 
#
ldapsearch -H ${urlAAI} -x -D "${binddnAAI}" -w "${bindpwAAI}" -b "${basednAAI}" "(hrEduPersonPrimaryAffiliation=djelatnik)" "uid"  > AAI.ldif
#
# process .ldif output so in one line is only users uid
#
# example: AAI.ldif contains ONLY users uid each in newline
# user1
# user2
# etc...
#
sed '/#/d' < AAI.ldif > newAAI.ldif; mv newAAI.ldif AAI.ldif
sed '/search:/d' < AAI.ldif > newAAI.ldif; mv newAAI.ldif AAI.ldif
sed '/result:/d' < AAI.ldif > newAAI.ldif; mv newAAI.ldif AAI.ldif
sed '/dn:/d' < AAI.ldif > newAAI.ldif; mv newAAI.ldif AAI.ldif
sed 's/uid: //' < AAI.ldif > newAAI.ldif; mv newAAI.ldif AAI.ldif
sed '/^$/d' < AAI.ldif > newAAI.ldif; mv newAAI.ldif AAI.ldif
#
# add users to array (each line in another member of array) and delete temporary file
#
declare -a AAIkorisnici
let i=0
while IFS=$'\n' read -r line_data; do
    AAIkorisnici[i]="${line_data}"
    ((++i))
done < AAI.ldif
rm -f AAI.ldif
#
# PROCESSING USERS
#
let i=0
while (( ${#AAIkorisnici[@]} > i )); do
#
# check if user already in Target LDAP (already have mailbox)
#
checkuserMAIL=$(ldapsearch -x -H ${urlMAIL} -b "${basednMAIL}" -D "${binddnMAIL}" -w "${bindpwMAIL}" uid=${AAIkorisnici[i]} | grep uid: | awk '{print $1}')
if [ "${checkuserMAIL}" = 'uid:' ]; 
    then
#
# user exist on Target LDAP ... so I will only synchronize password beetwen two LDAPs
#
        printf "Korisnik ${AAIkorisnici[i]} postoji na mail serveru\n";
        printf "Sinhromizacija mail lozinke sa AAI za: ${AAIkorisnici[i]}\n";
ldapsearch -H ${urlAAI} -x -D "${binddnAAI}" -w "${bindpwAAI}" -b "${basednAAI}" uid=${AAIkorisnici[i]} "(hrEduPersonPrimaryAffiliation=djelatnik)" "uid" "userPassword" | perl -MMIME::Base64 -MEncode=decode -n -00 -e 's/\n +//g;s/(?<=:: )(\S+)/decode("UTF-8",decode_base64($1))/eg;binmode(STDOUT, ":utf8");print' > userAAIpwtoMAILpw.ldif
#
# put user data in variables and delete temporary file
#
userUID=$(grep uid: userAAIpwtoMAILpw.ldif | awk '{print $2}')
userPASSWORD=$(grep userPassword: userAAIpwtoMAILpw.ldif | awk '{print $2}')
userMAIL=${userUID}@efzg.hr
rm -f userAAIpwtoMAILpw.ldif

ldapmodify -x -H ${urlMAIL} -D "${binddnMAIL}" -w "${bindpwMAIL}" <<EOF
dn: mail=${userMAIL},ou=Users,domainName=efzg.hr,${basednMAIL}
changetype: modify
replace: userPassword
userPassword: ${userPASSWORD}
EOF

    else
#
# user does not exist on Target LDAP so it will be added
#
        printf "Korisnik postoji u AAI ali ne i u mailu: ${AAIkorisnici[i]}\n";
    printf "Unosim korisnika u mail sustav : ${AAIkorisnici[i]}\n";
#
# get user data ftom Source LDAP (in my case i need: givenName, sn, userPassword, uid)
#
ldapsearch -H ${urlAAI} -x -D "${binddnAAI}" -w "${bindpwAAI}" -b "${basednAAI}" uid=${AAIkorisnici[i]} "(hrEduPersonPrimaryAffiliation=djelatnik)" "givenName" "sn" "userPassword" "uid"| perl -MMIME::Base64 -MEncode=decode -n -00 -e 's/\n +//g;s/(?<=:: )(\S+)/decode("UTF-8",decode_base64($1))/eg;binmode(STDOUT, ":utf8");print' > userAAItoMAIL.ldif
#
# put user data in variables and delete temporary file
#
userUID=$(grep uid: userAAItoMAIL.ldif | awk '{print $2}')
userGIVENNAME=$(grep givenName: userAAItoMAIL.ldif | awk '{print $2}')
userSN=$(grep sn: userAAItoMAIL.ldif | awk '{print $2}')
userPASSWORD=$(grep userPassword: userAAItoMAIL.ldif | awk '{print $2}')
userMAIL=${userUID}@efzg.hr
maildir="$( hash_domain "efzg.hr")/$( hash_maildir ${userUID} )"
rm -f userAAItoMAIL.ldif
#
# and finaly create user on mailserver....
#
ldapadd -x -H ${urlMAIL} -D "${binddnMAIL}" -w "${bindpwMAIL}" <<EOF
dn: mail=${userMAIL},ou=Users,domainName=efzg.hr,${basednMAIL}
objectClass: inetOrgPerson
objectClass: shadowAccount
objectClass: amavisAccount
objectClass: mailUser
objectClass: top
accountStatus: active
storageBaseDirectory: ${STORAGE_BASE}
homeDirectory: ${STORAGE_BASE_DIRECTORY}/${maildir}
mailMessageStore: ${STORAGE_NODE}/${maildir}
mail: ${userMAIL}
mailQuota: 1048576000
userPassword: ${userPASSWORD}
cn: ${userSN} ${userGIVENNAME}
sn: ${userSN}
givenName: ${userGIVENNAME}
uid: ${userUID}
shadowLastChange: 0
amavisLocal: TRUE
enabledService: internal
enabledService: doveadm
enabledService: lib-storage
enabledService: mail
enabledService: pop3
enabledService: pop3secured
enabledService: imap
enabledService: imapsecured
enabledService: managesieve
enabledService: managesievesecured
enabledService: sieve
enabledService: sievesecured
enabledService: smtp
enabledService: smtpsecured
enabledService: deliver
enabledService: lda
enabledService: forward
enabledService: senderbcc
enabledService: recipientbcc
enabledService: shadowaddress
enabledService: displayedInGlobalAddressBook
EOF

    fi
((++i))
done

.... and that it.

I'll later modify script to check if user exist on iRedMail LDAP and does not exist on Source LDAP and in that case to delete user from mail server (iRedMail LDAP)....

But this is something probably needed for many so i share one way LDAP sync script smile

----

Spider Email Archiver: On-Premises, lightweight email archiving software developed by iRedMail team. Supports Amazon S3 compatible storage and custom branding.

2

Re: Sync mail users with another LDAP server

kmihalj wrote:

#
# process .ldif output so in one line is only users uid
#

Not sure whether a 'grep/awk' will make this simpler. for example: grep '^uid:' AAI.ldif | awk '{print $2}'.

Will it be simpler if you dump UIDs from source and destination LDAP server, then compare them with "diff", filter out lines start with '-' and '+', then add/delete?

Looks like Python is better to do this. smile

3 (edited by kmihalj 2014-01-25 22:02:13)

Re: Sync mail users with another LDAP server

ZhangHuangbin wrote:
kmihalj wrote:

#
# process .ldif output so in one line is only users uid
#

Not sure whether a 'grep/awk' will make this simpler. for example: grep '^uid:' AAI.ldif | awk '{print $2}'.

Will it be simpler if you dump UIDs from source and destination LDAP server, then compare them with "diff", filter out lines start with '-' and '+', then add/delete?

Looks like Python is better to do this. smile

I know that python is better for that task, but, I'm prety rusty in Python smile

I just forgot about awk (yikes!) ... I implemented that (instead sed) ....

Diff is nice if list is sorted, but on password sync i have two parameters (uid and userPassword) ... so it is better with creating temp ldif ... I know that it is lots of LDAP bind's (I have cca 11000 users) but I'll run script once a day... and script runs cca 1 min 

I now need to findout how to disable password change, and to add "wraper" or link for site where password can be changed instead "change password" screen in roundcube....

4

Re: Sync mail users with another LDAP server

I tried the script and it works fine, it's an old subject but is ther any chance you have the finished 2 way sync script you're talking about ?

I'll later modify script to check if user exist on iRedMail LDAP and does not exist on Source LDAP and in that case to delete user from mail server (iRedMail LDAP)....

Thanks

5

Re: Sync mail users with another LDAP server

YannF wrote:

is ther any chance you have the finished 2 way sync script you're talking about ?

not yet and no plan to do so. sorry.