配置OpenLDAP密码到期电子邮件通知

在本教程中,我们将学习如何配置OpenLDAP密码到期电子邮件通知。如果您在OpenLDAP客户端上使用诸如SSSD之类的身份和身份验证客户端,则可能已经意识到,每次登录系统时,SSSD都会显示密码过期的天数,即只有OpenLDAP密码过期策略有效已经实施。

但是,最终用户始终是最终用户。他们将始终忽略这些通知。他们从不喜欢更改密码的想法:)。因此,采用不同的方式来通知他们,甚至系统管理员也可以自行通知密码过期是一个好主意。因此,本教程将提供一些基本步骤,以配置OpenLDAP以通过电子邮件将通知发送到用户邮箱,通知用户密码到期。

在之前的指南中,我们学习了如何实施OpenLDAP密码策略。下面提供了链接;

实施OpenLDAP密码策略

同样,我们还介绍了用户如何使用OpenLDAP自助密码工具自行重置自己的OpenLDAP密码。

在CentOS 8上设置LDAP自助服务密码工具

配置OpenLDAP密码到期电子邮件通知

在搜寻Internet如何配置OpenLDAP密码到期电子邮件通知时,我们遇到了 LDAP工具箱(LTB),该脚本已编写为浏览LDAP目录以查找使用密码策略的条目。如果用户的密码即将过期,则会发送一封邮件。

该脚本已通过OpenLDAP(策略覆盖)进行了测试。我们提供了一个链接,用于使用 ppolicy overlay 以上。

检查LDAP密码过期脚本

我们下载了脚本并对其进行了修改,以适应我们的OpenLDAP目录设置。它可以将电子邮件通知发送给其帐户密码处于警告状态的用户,同时将统计信息发送给特定的管理员。

以下是修改后的脚本的内容,其中删除了注释行。

脚本的原始版本可以在以下位置找到 LTB Github LDAP脚本存储库

grep -Ev "^s[#;]|^s$|^#" checkLdapPwdExpiration.sh
MY_LDAP_HOSTURI="ldapi:///"
MY_LDAP_DEFAULTPWDPOLICYDN="cn=default,ou=pwpolicy,dc=ldapmaster,dc=kifarunix-demo,dc=com"
MY_LDAP_SEARCHBASE="ou=people,dc=ldapmaster,dc=kifarunix-demo,dc=com"
MY_LDAP_SEARCHFILTER="(&(uid=*)(objectClass=inetOrgPerson))"
MY_LDAP_SEARCHSCOPE="one"
MY_LDAP_SEARCHBIN="/usr/bin/ldapsearch"
MY_LDAP_NAME_ATTR=cn
MY_LDAP_LOGIN_ATTR=uid
MY_LDAP_MAIL_ATTR=mail
export LC_ALL=en_US.UTF-8
MY_MAIL_BODY="Hi %name,nn 
	Your password will expire in %expireDays days on %expireTimeTZ.nn 
        Visit Kifarunix-demo Self Service Password site, https://ldap-ssp.kifarunix-demo.com to reset your password.nn 
	As a reminder, ensure that your password conforms to the company outlined password policies.nn 
	Kifarunix-demo IT team,n
	Regards."
EX_MAIL_BODY="Hi %name,nn 
	Your password expired on %expireTimeTZ.nn 
        Kindly contact Kifarunix-demo IT team to help reset the password.nn 
	Kifarunix-demo IT team,n
	Regards."
MY_MAIL_SUBJECT="LDAP Account Password Expiry Status"
MY_MAIL_BIN="mail"
MY_LOG_HEADER="`date +"%b %e,%Y %T"`"
MY_GAWK_BIN="/usr/bin/gawk"
getTimeInSeconds() {
	date=0
	os=`uname -s`
	if [ "$1" ]; then
		date=`${MY_GAWK_BIN} 'BEGIN  { 
			if (ARGC == 2) { 
		        	print mktime(ARGV[1]) 
			} 
			exit 0 }' "$1"`
	else
		if [ "${os}" = "SunOS" ]; then
			date=`/usr/bin/truss /usr/bin/date 2>&1 | nawk -F= 
				'/^time()/ {gsub(/ /,"",$2);print $2}'`
		else
			now=`date +"%Y %m %d %H %M %S" -u`
			date=`getTimeInSeconds "$now"`
		fi
	fi
	echo ${date}
}
tmp_dir="/tmp/$$.checkldap.tmp"
result_file="${tmp_dir}/res.tmp.1"
buffer_file="${tmp_dir}/buf.tmp.1"
tmp_dir_stats="/tmp/ldap-password-stats"
ldap_param="-Y EXTERNAL -H ${MY_LDAP_HOSTURI} -LLL -Q"
nb_users=0
nb_expired_users=0
nb_warning_users=0
if [ -d ${tmp_dir} ]; then
	echo "Error : temporary directory exists (${tmp_dir})"
	exit 1
fi
mkdir ${tmp_dir}
if [ ${MY_LDAP_ROOTDN} ]; then
	ldap_param="${ldap_param} -D ${MY_LDAP_ROOTDN} -w ${MY_LDAP_ROOTPW}"
fi
${MY_LDAP_SEARCHBIN} ${ldap_param} -s ${MY_LDAP_SEARCHSCOPE} 
	-b "${MY_LDAP_SEARCHBASE}" "${MY_LDAP_SEARCHFILTER}" 
	"dn" > ${result_file}
while read dnStr
do
	if [ ! "${dnStr}" ]; then
		continue
	fi
	dn=`echo ${dnStr} | cut -d : -f 2`
	nb_users=`expr ${nb_users} + 1`
	${MY_LDAP_SEARCHBIN} ${ldap_param} -s base -b "${dn}" 
		${MY_LDAP_NAME_ATTR} ${MY_LDAP_LOGIN_ATTR} ${MY_LDAP_MAIL_ATTR} pwdChangedTime pwdPolicySubentry 
		> ${buffer_file}
	login=`grep -w "${MY_LDAP_LOGIN_ATTR}:" ${buffer_file} | cut -d : -f 2 
		| sed "s/^ *//;s/ *$//"`
	name=`grep -w "${MY_LDAP_NAME_ATTR}:" ${buffer_file} | cut -d : -f 2
		| sed "s/^ *//;s/ *$//"`
	mail=`grep -w "${MY_LDAP_MAIL_ATTR}:" ${buffer_file} | cut -d : -f 2 
		| sed "s/^ *//;s/ *$//"`
	pwdChangedTime=`grep -w "pwdChangedTime:" ${buffer_file} 
		| cut -d : -f 2 | cut -c 1-15 | sed "s/^ *//;s/ *$//"`
	pwdPolicySubentry=`grep -w "pwdPolicySubentry:" ${buffer_file} 
		| cut -d : -f 2 | sed "s/^ *//;s/ *$//"`
	if [ ! "${pwdChangedTime}" ]; then
		echo "No password change date for ${login} (${mail})" >> ${tmp_dir_stats}
		continue
	fi
	if [ ! "${pwdPolicySubentry}" -a ! "${MY_LDAP_DEFAULTPWDPOLICYDN}" ]; then
		echo "No password policy for ${login} (${mail})" >> ${tmp_dir_stats}
		continue
	fi
	ldap_search="${MY_LDAP_SEARCHBIN} ${ldap_param} -s base"
	if [ "${pwdPolicySubentry}" ]; then
		ldap_search="${ldap_search} -b ${pwdPolicySubentry}"
	else
		ldap_search="${ldap_search} -b ${MY_LDAP_DEFAULTPWDPOLICYDN}"
	fi
	ldap_search="$ldap_search pwdMaxAge pwdExpireWarning pwdMinLength pwdInHistory"
	pwdMaxAge=`${ldap_search} | grep -w "pwdMaxAge:" | cut -d : -f 2 
		| sed "s/^ *//;s/ *$//"`
	pwdExpireWarning=`${ldap_search} | grep -w "pwdExpireWarning:" | cut -d : -f 2 
		| sed "s/^ *//;s/ *$//"`
	pwdMinLength=`${ldap_search} | grep -w "pwdMinLength:" | cut -d : -f 2 
		| sed "s/^ *//;s/ *$//"`
	pwdInHistory=`${ldap_search} | grep -w "pwdInHistory:" | cut -d : -f 2 
		| sed "s/^ *//;s/ *$//"`
        if [ ! "${pwdMaxAge}" ]; then
                echo "No password expiration configured for ${login} (${mail})" >> ${tmp_dir_stats}
                continue
        fi
	MY_MAIL_DELAY=${MY_MAIL_DELAY:=$pwdExpireWarning}
	if [ "${pwdChangedTime}" ]; then
		s=`echo ${pwdChangedTime} | cut -c 13-14`
		m=`echo ${pwdChangedTime} | cut -c 11-12`
		h=`echo ${pwdChangedTime} | cut -c 9-10`
		d=`echo ${pwdChangedTime} | cut -c 7-8`
		M=`echo ${pwdChangedTime} | cut -c 5-6`
		y=`echo ${pwdChangedTime} | cut -c 1-4`
		currentTime=`getTimeInSeconds`
		pwdChangedTime=`getTimeInSeconds "$y $M $d $h $m $s"`
		diffTime=`expr ${currentTime} - ${pwdChangedTime}`
	fi
	expireTime=`expr ${pwdChangedTime} + ${pwdMaxAge}`
	if [ ${currentTime} -gt ${expireTime} ]; then
		nb_expired_users=`expr ${nb_expired_users} + 1`
		expireTime=`date -d @$expireTime "+%A %d, %B %Y at %T"`
	        logmsg="${EX_MAIL_BODY}"
		logmsg=`echo -e ${logmsg} | sed "s/%name/${name}/; 
			s/%login/${login}/; s/%expireTimeTZ/${expireTime}/; s/%pwdMinLength/${pwdMinLength}/; s/%pwdInHistory/${pwdInHistory}/; 
			s/%expireDays/${expireDays}/"`
		echo "${logmsg}" | ${MY_MAIL_BIN} -s "${MY_MAIL_SUBJECT}" ${mail} >&2
		echo "Password expired for ${login} on ${expireTime}. Mail sent to ${mail}" >> ${tmp_dir_stats}
		continue
	fi
	expireTimeTZ=`date -d @$expireTime "+%A %d, %B %Y at %T"`
	expireTimeMail=`date -d @$expireTime "+%s"`
	now=`date +%s`
	expireDays=`echo $(( (${expireTimeMail} - ${now} )/(60*60*24) ))`
	if [ "${mail}" -a "${name}" 
		-a "${login}" -a "${diffTime}" -a "${pwdMaxAge}" ]
	then
		diffTime=`expr ${diffTime} + ${MY_MAIL_DELAY}`
		if [ ${diffTime} -gt ${pwdMaxAge} ]; then
			logmsg="${MY_MAIL_BODY}"
			logmsg=`echo -e ${logmsg} | sed "s/%name/${name}/; 
				s/%login/${login}/; s/%expireTimeTZ/${expireTimeTZ}/; s/%pwdMinLength/${pwdMinLength}/; s/%pwdInHistory/${pwdInHistory}/; 
				s/%expireDays/${expireDays}/"`
			echo "${logmsg}" | ${MY_MAIL_BIN} -s "${MY_MAIL_SUBJECT}" ${mail} >&2
			echo "Password warning for ${login} (expiry date, ${expireTimeTZ}). Mail sent to ${mail}" >> ${tmp_dir_stats}
			nb_warning_users=`expr ${nb_warning_users} + 1`
		fi
	fi
done < ${result_file}
sed -i "1iHello Admin,nFind the LDAP users account password expiry status as at ${MY_LOG_HEADER}.n" ${tmp_dir_stats}
echo "Total User Accounts checked: ${nb_users}" >> ${tmp_dir_stats}
echo "Accounts with Expired Passwords: ${nb_expired_users}" >> ${tmp_dir_stats}
echo "Accounts with Passwords in Warning state: ${nb_warning_users}" >> ${tmp_dir_stats}
sed -i -e '/^Total.*/i\ ' -e '/^Total.*/i ===== Statistics =====' ${tmp_dir_stats}
mail -s "LDAP Password Expiration Status" [email protected] < ${tmp_dir_stats}
rm -rf ${tmp_dir}
rm -rf ${tmp_dir_stats}
exit 0

脚本要求

正如LTB页面上概述的那样,脚本需要;

  • gawk(GNU awk)(which gawk
  • ldapsearch(which ldapsearch
  • mailx(提供mail命令, which mailx
  • 日期(which date

which 实用程序使您可以检查命令是否已安装以及其位置的完整路径。

脚本变量

另外,相应地在脚本上更新以下变量。

  • MY_LDAP_HOSTURI:LDAPURI
  • MY_LDAP_ROOTDN (可选):用于绑定的DN。没有DN表示匿名
  • MY_LDAP_ROOTPW:密码
  • MY_LDAP_DEFAULTPWDPOLICYDN:默认密码策略DN。如果未使用默认策略,则不设置。在这种情况下,该脚本只会影响在其条目(pwdPolicySubentry)中使用密码策略的用户
  • MY_LDAP_SEARCHBASE:用户搜索库
  • MY_LDAP_SEARCHFILTER:用户搜索过滤器
  • MY_LDAP_SEARCHBIN:ldapsearch二进制文件的路径
  • MY_MAIL_DELAY:到期之前发送邮件的时间。到期后未发送任何邮件。如果没有值,则脚本将采用密码策略的pwdExpireWarning
  • MY_LDAP_NAME_ATTR:包含用户名的属性
  • MY_LDAP_LOGIN_ATTR:包含用户登录名的属性
  • MY_LDAP_MAIL_ATTR:包含用户名的属性
  • MY_MAIL_BODY: 邮件正文
  • MY_MAIL_SUBJECT: 信息主题
  • MY_MAIL_BIN:二进制邮件
  • MY_LOG_HEADER:日志头
  • MY_GAWK_BIN:gawk二进制文件的路径

样本LDAP用户条目

以下是我们的示例OpenLDAP用户条目。请注意以下属性;

  • MY_LDAP_NAME_ATTR=cn
  • MY_LDAP_LOGIN_ATTR=uid
  • MY_LDAP_MAIL_ATTR=mail
ldapsearch -Y EXTERNAL -H ldapi:/// -s one -b "ou=people,dc=ldapmaster,dc=kifarunix-demo,dc=com" -LLL -Q uid=janedoe 
dn: uid=janedoe,ou=people,dc=ldapmaster,dc=kifarunix-demo,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
objectClass: extensibleObject
uid: janedoe
cn: Jane
sn: Doe
loginShell: /bin/bash
uidNumber: 10010
gidNumber: 10010
homeDirectory: /home/janedoe
shadowMax: 60
shadowMin: 1
shadowWarning: 7
shadowInactive: 7
shadowLastChange: 0
userPassword:: e1NTSEF9dmczUGpBa0EybUtOanJ4QWc1dWN5d20wNnlmOGg4cE8=
mail: [email protected]

测试LDAP密码到期通知脚本

要检查脚本可以使我们得到期望的结果,只需按以下步骤在LDAP服务器上执行该脚本即可;

bash checkLdapPwdExpiration.sh

我们的脚本将输出写入, /tmp/ldap-password-stats,文件。

cat /tmp/ldap-password-stats
Hello Admin,
Find the LDAP users account password expiry status as Jun 13,2020 21:19:18.

Password warning for janedoe (expiry date, Thursday 18, June 2020 at 11:12:37). Mail sent to [email protected]
Password expired for koromicha on Friday 08, May 2020 at 21:34:02. Mail sent to [email protected]
No password change date for johndoe ([email protected])

===== Statistics =====
Total User Accounts checked: 4
Accounts with Expired Passwords: 1
Accounts with Passwords in Warning state: 1

从上面的输出中,我们可以看到;

  • 在目录中,总共检查了四个用户。
  • 用户密码 koromicha,已于2020年5月8日(星期五)21:34:02到期。通知电子邮件已发送给用户。
  • 用户密码, janedoe,将于2020年6月18日(星期四)11:12:37到期。通知电子邮件已发送给用户。
  • johndoe的密码更改日期([email protected])

由于我们没有安装任何邮件实用程序,因此您可能会得到这样的输出;

mail: command not found

配置您的LDAP服务器发送邮件

为了使您的OpenLDAP服务器能够发送邮件,您需要安装和配置MTA。如果您在上面注意到,该脚本尝试使用 sendmail。在此演示中,我们将改用后缀。

请注意,我们的LDAP服务器在CentOS 8系统上运行

在CentOS 8上安装和设置OpenLDAP

在CentOS 8上安装Postfix MTA

yum install postfix cyrus-sasl-plain mailx

配置Postfix以使用Gmail SMTP中继

cp /etc/postfix/main.cf /etc/postfix/main.cf.old
vim /etc/postfix/main.cf

进行以下调整;

myhostname = ldap.kifarunix-demo.com
inet_protocols = ipv4
relayhost = [smtp.gmail.com]:587
smtp_use_tls = yes
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous

保存并退出配置。

在文件上输入身份验证凭据, /etc/postfix/sasl_passwd 格式

[smtp.gmail.com]:587 [email protected]:password

散列凭证文件。

postmap /etc/postfix/sasl_passwd

在凭据文件上设置适当的权限,

chown root:postfix /etc/postfix/sasl_passwd*
chmod 640 /etc/postfix/sasl_passwd*

启动Postfix配置。

systemctl enable --now postfix

测试电子邮件传递

echo "Test Postfix gmail relay" | mail -s "Test postfix gmail relay" [email protected]

检查日志。

tail /var/log/maillog

如果看到这条线,一切就很好了;

[email protected], relay=smtp.gmail.com[74.125.133.108]:587, ...status=sent (250 2.0.0 OK ..

电子邮件中继配置完成后,请重新运行脚本。

bash checkLdapPwdExpiration.sh

检查在此演示中设置为的管理员收件箱, [email protected],以及密码处于警告状态的用户的收件箱, [email protected]

在“管理邮箱”上,这是LDAP发出的电子邮件;

Subject: LDAP Password Expiration Status

Hello Admin,
Find the LDAP users account password expiry status as Jun 13,2020 21:31:11.

Password warning for janedoe (expiry date, Thursday 18, June 2020 at 11:12:37). Mail sent to [email protected]
Password expired for koromicha on Friday 08, May 2020 at 21:34:02. Mail sent to [email protected]
No password change date for johndoe ([email protected])

===== Statistics =====
Total User Accounts checked: 4
Accounts with Expired Passwords: 1
Accounts with Passwords in Warning state: 1

在用户的收件箱中(在这种情况下为Janedoe和Koromicha);

Subject: LDAP Account Password Expiry Status

Hi jane,

 Your password will expire in 4 days on Thursday 18, June 2020 at 11:12:37.

 Visit Kifarunix-demo Self Service Password site, https://ldap-ssp.kifarunix-demo.com to reset your password.

 As a reminder, ensure that your password conforms to the company outlined password policies.

 Kifarunix-demo IT team,
 Regards.
Subject: LDAP Account Password Expiry Status

Hi koromicha,

 Your password expired on Friday 08, May 2020 at 21:34:02.

 Kindly contact Kifarunix-demo IT team to help reset the password.

 Kifarunix-demo IT team,
 Regards.

然后你去。现在,您以管理员身份收到LDAP帐户密码到期的状态。同时,通过其LDAP条目中定义的相应电子邮件,通知密码尚未过期的用户。我们希望那是有益的。

为脚本创建每日Cron作业

为了确保定期执行脚本,您要做的就是创建一个cron作业,以在特定的固定时间执行脚本,并将LDAP帐户密码状态发送给用户。

在安装cron作业之前,请确保脚本是可执行的。

chmod +x /home/kifarunix/checkLdapPwdExpiration.sh

要安装cron作业,请运行以下命令;

crontab -e

输入以下行,以使脚本从星期一至星期五每天0800小时执行。

0 8 * * 1-5 /home/kifarunix/checkLdapPwdExpiration.sh

这标志着我们有关如何配置OpenLDAP密码到期电子邮件通知的指南的结尾。

Sidebar