Active Directory Based Zimbra Collaboration OSE User Sync

1. الخلفية


عند تكوين خادم zimbra ، واجهت مشكلة مزامنة المستخدمين حسب المجموعة في Active Directory (AD). إذا قمنا بإنشاء مستخدم جديد في AD ، فسيتم إضافته عادةً ، ولكن إذا تمكنا من الوصول إلى خادم البريد حسب المجموعة ، فسيتم مزامنة جميع المستخدمين للمرة الأولى. ولكن بعد ذلك ، لا تؤثر التغييرات في المجموعة على التغييرات في مستخدمي خادم بريد zimbra.

ما لم يعجبه في هذه المقالات هو استخدام البرنامج النصي powerhell (لماذا ، إذا كان هناك ldapsearch) والاستخدام المستمر لأداة zmprov ، وعندما تتم مزامنة عدد كبير من المستخدمين ، يتم تشغيل البرنامج النصي لفترة طويلة

2. بيانات المصدر


خادم نظام التشغيل: CentOS 7
لغة البرنامج النصي: bash
Zimbra مجال: test.ru
Zimbra server: zimbra.test.local
مجال Active Directory: test.local
AD group للوصول إلى البريد: mail

قد يكون لدى المستخدم بريد مختلف عن تسجيل الدخول الخاص به ، مثل هذا البريد إضافته إلى AD في حقل البريد واستخدامه لإنشاء اسم مستعار في zimbra (على سبيل المثال ، Vasya Pupkin بتسجيل الدخول إلى النظام باستخدام اسم المستخدم vasia ، ولكن يجب إرسال البريد واستلامه كمستخدم v.pupkin@test.ru)

3. مخطط البرنامج النصي


  1. حفظ في ملف مستخدم AD مضمن في مجموعة البريد
  2. نقوم بحفظ جميع مستخدمي zimbra بكل سمات الملف
  3. نقسم الملف بقائمة بجميع مستخدمي zimbra إلى ملفات تنسيق: اسم الملف - تسجيل دخول المستخدم ، المحتوى - سمات المستخدم
  4. نقوم بإزالة من قائمة حسابات نظام zimbra للمستخدمين (admin ، gal ، antivirus)
  5. قارن بين قائمة مستخدمي AD وزيمبرا
  6. قم بإنشاء ملف بالأوامر لإضافة وحذف (في حالتي ، حظر المستخدم) ومزامنة وإنشاء الأسماء المستعارة
  7. تطبيق هذه الإجراءات في zimbra (مكالمة واحدة إلى zmprov)
  8. إرسال تقرير إلى المسؤول عن طريق البريد (إذا كان لديك شيء لإرساله)
  9. حذف الملفات والأدلة المؤقتة

4. مزامنة البرنامج النصي


يحتوي البرنامج النصي على وضعين للتشغيل - يتم تشغيل هذا بدون معلمات ، ثم يعمل حظر المستخدمين وإضافتهم فقط. وابدأ بمعلمة "الكل" ، ثم تتم مزامنة جميع مستخدمي مجموعة البريد في م.

من الضروري أيضًا الانتباه إلى استخدام أداة فك الترميز base64 في وظيفة المزامنة ، يجب استخدامها لحقول AD التي يتم فيها استخدام الأحرف الروسية.

النص نفسه:
#!/bin/bash
#
#1.  
#
#1.1  
#   
path="/mnt/zimbra/user-sync"
# 
timestamp=`date +%F-%H-%M`
#   
tmp_dir=$path/tmp
#      zimbra
zim_us=$tmp_dir/zim-us
#   
log_dir=$path/log
# -
log=$log_dir/grouplog_$timestamp.txt
#      
usname=$tmp_dir/usname
#          zmprov
zmcmdfile=$tmp_dir/zmcmdfile
#        AD 
userfil=$tmp_dir/userfil
# 
mutt="/usr/bin/mutt"

#
#1.2   zimbra
#  Zimbra
domain="test.ru"
#   zmprov
zmprov="/opt/zimbra/bin/zmprov"
#
#1.3    AD  LDAP
#LDAP search
ldapsearch=/opt/zimbra/common/bin/ldapsearch
#    ( ,   (   ))
ldap_server="ldap://test.local:389"
# OU 
basedn="DC=test,DC=local"
#      AD  LDAP
binddn="CN=zimbra,CN=Users,DC=test,DC=local"
bindpw="qwe123" #user password 
#  -     mail
filter="(memberof=cn=mail,cn=users,dc=test,dc=local)"
#    (,             )
fields="sAMAccountName mail description displayName givenName cn sn department title"
#  

# 

# 
#   
function err_log()
{
if [ $1 -eq 0 ]; then
		#echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]"
		#echo
		echo $2" [Ok]"  >> $log
	else
		#echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]"
		#echo
		echo  $2" [Fail]" >> $log
	fi
}

#  
function if_path ()
{
	#      
	if [ ! -d $1 ]; then
	#   
	echo "  $1..." >> $log
	mkdir -p $1
	err_log $? "  $1"
	
else
	echo "  $1 " >> $log	
fi
}

#      AD
function search_users_AD()
{
	echo "     AD..." >> $log
	$ldapsearch -x -o ldif-wrap=no -H $ldap_server -D $binddn -w $bindpw -b $basedn $filter $fields | 
	grep sAMAccountName | 
	egrep -v '^#|^$' | 
	awk '{print $2}' |
	sort > $usname.ad
	echo "Found () "`cat $usname.ad | wc -l`" Group in AD (  AD)" >> $log
}

function all_user_attr_zimbra()
{
	#        
	$zmprov -l gaa -v $domain > $usname.gaa
	#         
	cd $zim_us
	#      ,     
	csplit $usname.gaa --prefix='user.' --suffix-format='%03d.zim' --elide-empty-files -s /"# name"/ '{*}'

	#   .      zimbra  
	for i in $( ls $zim_us )
	do
		nam=`grep "# name" $zim_us/$i | awk '{ print $3}' | sed 's/@.*//g'`
		mv -f $zim_us/$i $zim_us/$nam
	done
	cd $path
}

#      zimbra 
function search_user_zimbra()
{
	echo "    zimbra..." >> $log
	ls $zim_us | sort > $usname.tem
	#    .  $path/system.acc    
	diff -u -i $usname.tem $path/system.acc  | sed 1,3d | grep ^- | cut -c 2- | sort > $usname.zim
	#rm -f $usname.tem
	echo "Found () "`cat $usname.zim | wc -l`" Group in Zimbra (  Zimbra)" >> $log
	
}

#    (   
function diff_user_list()
{
	diff -u -i $usname.zim $usname.ad | sed 1,3d | sed '/@.*/d' > $usname.diff
}

# 
function adduser()
{
#    	
adddif=`grep ^+ $usname.diff | sed '1!d'`
	if [ -n $adddif ];
	then
		for addus in $( grep ^+ $usname.diff | cut -c 2- )
		do
			#       zimbra (  - ,  - )
                        ifclos=`grep "zimbraAccountStatus:" $zim_us/$addus | awk '{print $2}' | cut -c -1`
			if [ $ifclos = "c" ];
			then
				echo "ma $addus@$domain zimbraAccountStatus active" >> $zmcmdfile
				echo " $addus " >> $tmp_dir/send.txt
				if [ $addus != "" ];
				then
					sync_one_user $addus
				fi
			else
				#123456 -  ,    .   ,         AD
				echo "ca $addus@$domain 123456" >> $zmcmdfile
				echo " $addus " >> $tmp_dir/send.txt
				if [ $addus != "" ];
				then
					sync_one_user $addus
				fi
			fi
		done
		
	fi
}

#   
function block_user()
{
	deldif==`grep ^- $usname.diff | sed '1!d'`
	if [ -n $deldif ];
	then
		for delus in $( grep ^- $usname.diff | cut -c 2- )
		do
			#zimbraAccountStatus closed
			if [ $delus != "" ];
			then
				ifclos=`grep "zimbraAccountStatus:" $zim_us/$delus | awk '{print $2}'`
				if [ "$ifclos" != "closed" ];
				then
					echo "user closed - $delus"
					echo "ma $delus@$domain zimbraAccountStatus closed" >> $zmcmdfile
					echo " $delus !     !" >> $tmp_dir/send.txt
					echo $delus >> $path/close.1
					cat $path/close.1 | sort > $path/close.diff
					echo "$delus" 
				fi
			fi
		done
	fi
}

#   
function ifattr()
{
	if1char=`echo $2 | cut -c -1`
	if [[ -n $2 && $if1char != "" ]];
	#if [ $2 != "" ];
	then 
	    #echo $2
	    echo -n " $1 \"$2\""  >> $zmcmdfile
	fi
}

#  
function sync_one_user()
{
	echo "  $1..." >> $log
	$ldapsearch -x -o ldif-wrap=no -H $ldap_server -D $binddn -w $bindpw -b $basedn "(sAMAccountName=$1)" $fields > $userfil/$1.ad
	
	#   
	echo -n  "ma "$1 >> $zmcmdfile
	
	#samacc=`grep "sAMAccountName:" $userfil/$1 | awk '{print $2}'`  
		
	description=`grep "description:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}'`
	#echo $description
	ifattr "description" "$description"
		
	displayName=`grep "displayName:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}' | base64 -d`
	ifattr "displayName" "$displayName"
	
	givenName=`grep "givenName:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}' | base64 -d`
	ifattr "givenName" "$givenName"
	
	cn=`grep "cn:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}'`
	ifattr "cn" "$cn"
	
	sn=`grep "sn:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}' | base64 -d`
	ifattr "sn" "$sn"
	
	department=`grep "department:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}' | base64 -d`
	ifattr "company" "$department"
	
	title=`grep "title:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}' | base64 -d`
	ifattr "title" "$title"
	
	#    
	echo >> $zmcmdfile
	# 
	mailnew=`grep "mail:" $userfil/$1.ad | awk '{print $2}'`
	if [ "$mailnew" != "" ];
	then 
	# [ -n $mailnew ] 
	#    echo $2
		#    
		#${1,,} -      
		useralias=`grep "zimbraMailAlias:" $zim_us/${1,,} | awk '{print $2}'`
	    if [ $useralias != $mailnew ];
		then
			echo "aaa \"$1@$domain\" \"$mailnew\""  >> $zmcmdfile
		fi
	fi
	#ifattr "mail" $mailnew
#	echo $mailnew
	echo "  $1 " >> $tmp_dir/send.txt 
	
#	echo " $1 - $atrruser"
	
	#echo "Found () "`cat $usname.ad | wc -l`" Group in AD (  AD)" >> $log
}


# 
date +%F-%H-%M
#2.  
#  
if_path $path
#  
if_path $tmp_dir
# -
if_path $log_dir
#   
if_path $userfil
#    
if_path $zim_us

#         zmprov
:> $zmcmdfile
#    
:> $tmp_dir/send.txt
#3.     AD 
search_users_AD

#4.    zimbra 
all_user_attr_zimbra
#  ()
search_user_zimbra

#5.    
diff_user_list
# 
block_user
#    
adduser

#tckb    "all"  ,        mail AD
if [[ -n $1 && $1 = "all" ]];
then
	for us in $(cat $usname.ad );
	do
	#	echo $us
		sync_one_user $us
	done
fi
#      zmprov  
$zmprov -f $zmcmdfile
#       
cat $zmcmdfile >> $log
#     (  )
if [ -s $tmp_dir/send.txt ];
then
	$mutt  -s "   $timestamp" admins@test.ru -a $log < $tmp_dir/send.txt
fi

#    
rm -R -f $tmp_dir


5. الخلاصة


بشكل عام ، تبين أن البرنامج النصي سريع جدًا ، ويتم استخدام الأداة المساعدة zmprov مرتين فقط ، بينما تعمل بقية الأدوات المساعدة والوظائف بشكل أسرع.

6 - المراجع


عند إنشاء هذه المقالة ، تم استخدام الأفكار والمقالات:

1. Andrey Sysoev
2. DruGoeDeLo
3. تعليقي على المادة 1) مع برنامج نصي لمزامنة القوائم البريدية

All Articles