Помните, когда общество наше перешло от собирательства к взращиванию, появилось такое понятие, как разделение труда. Идея в том, что кузнец куёт, косец косит, пекарь выпекает, а кто-то съедает результат. Многим это пришлась по душе. Потребители радостно устремились к состоянию чистого потребительства, не желая давать себе труда пошевелить чем бы то ни-было, кроме как челюстями.
Доходит до смешного, выдаёшь человеку сертификат доступа к VPN, в котором вписан срок его действия, и выясняется, оказывается - ты же ещё и обязан напомнить вовремя потребителю о том, что срок вот-вот закончится. Интересно, кто таким деятелям напоминает о сроке хранения продуктов или о необходимости вовремя налоги заплатить?
Ну, да ладно, нужно - значит делаем. Всё просто, напишем скрипт, пробегающийся по индексу используемых OpenVPN сервером сертификатов и отправляем уведомление, буде в этом возникнет необходимость, на адреса электронных почтовых ящиках, указанные при генерации сертификатов.
Для начала оборудуем местечко для сохранения журнала отправленных уведомлений:
# mkdir -p /var/log/openvpn
# touch /var/log/openvpn/check-expare.log
# chown openvpn:openvpn /var/log/openvpn/check-expare.log
# chmod o-rwx /var/log/openvpn/check-expare.log
# touch /var/log/openvpn/check-expare.log
# chown openvpn:openvpn /var/log/openvpn/check-expare.log
# chmod o-rwx /var/log/openvpn/check-expare.log
Размещаем где-нибудь наш скрипт:
# mkdir -p /etc/custom/openvpn
# touch /etc/custom/openvpn/check-expare.sh
# chmod ugo+x /etc/custom/openvpn/check-expare.sh
# touch /etc/custom/openvpn/check-expare.sh
# chmod ugo+x /etc/custom/openvpn/check-expare.sh
Содержимое следует:
# cat /etc/custom/openvpn/check-expare.sh
#!/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
HOSTNAME=`cat /etc/hostname`
MAILADM=support@vpn.example.local
# Указываем месторасположение файлов сертификатов
KEYS=/etc/openvpn/easy-rsa/keys/
# Указываем имя и местораположение индекса используемых сервером сертификатов
INDEX=/etc/openvpn/easy-rsa/keys/index.txt
# Указываем имя и месторасположение индекса рассылки
LOG=/var/log/openvpn/check-expare.log
# Задаём временные метки для инициирования высылки уведомления
AMONTH=2678400
AWEEK=604800
ATREEDAY=259200
# Запускаем перебор строк файла индекса (отрабатываем только задействованные, не отозванные)
cat $INDEX | grep '^V' | while read LINE
do
# Получаем имя сертификата
CN=`echo $LINE | awk 'match($0,/\/CN=.+\//) {print substr($0, RSTART, RLENGTH)}' | cut -c 5- | rev | cut -c 5- | rev`
# Получаем адрес электронного почтового ящики, на который будем слать уведомления
emailAddress=`echo $LINE | awk 'match($0,/\/emailAddress=.+/) {print substr($0, RSTART, RLENGTH)}' | cut -c 15- | rev | cut -c 1- | rev`
# Получаем дату начала действия сертификата
DFROM=`cat ${KEYS}/${CN}.crt | grep -i "Not Before" | awk 'match($0,/: .+/) {print substr($0, RSTART, RLENGTH)}' | cut -c 3- | rev | cut -c 1- | rev`
# Получаем дату окончания действия сертификата
DTO=`cat ${KEYS}/${CN}.crt | grep -i "Not After" | awk 'match($0,/: .+/) {print substr($0, RSTART, RLENGTH)}' | cut -c 3- | rev | cut -c 1- | rev`
# Приводим значения полученных дат к единому образцу - времени, прошедшему от начала "эпохи" UNIX (seconds since 1970-01-01 00:00:00 UTC)
DCURR=`date +%s`
DFROM=`date --date="${DFROM}" +%s`
DTO=`date --date="${DTO}" +%s`
# Вычисляем, сколько секунд осталось до окончания действия сертификата
DEXP=`expr ${DTO} - ${DCURR}`
# Проверяем, не настало-ли время
if [ ${DEXP} -lt ${ATREEDAY} ]
then
# Если событие по сроку информирования для проверяемого сертификата не зафиксировано, то делаем это
if [ "`cat ${LOG} | grep -i ${CN} | grep -i ATREEDAY`" == "" ] || [ `cat ${LOG} | sort --reverse | grep -i ${CN} | grep -i --max-count=1 ATREEDAY | awk '{print $1}'` -lt ${DFROM} ]
then
# Высылаем уведомление на адрес электронной почты, указанный при создании сертификата
echo -e "Content-Type: text/plain; charset="utf-8"\nSubject: Warning from ITS VPN server to ${CN}\nДо окончания срока действия сертификата (VPN) удалённого доступа осталось три дня." | sendmail -F${HOSTNAME} ${emailAddress} ${MAILADM}
# Записываем в журнал событие
echo "${DCURR} ${CN} ATREEDAY" >> ${LOG}
fi
else
if [ ${DEXP} -lt ${AWEEK} ]
then
if [ "`cat ${LOG} | grep -i ${CN} | grep -i AWEEK`" == "" ] || [ `cat ${LOG} | sort --reverse | grep -i ${CN} | grep -i --max-count=1 AWEEK | awk '{print $1}'` -lt ${DFROM} ]
then
echo -e "Content-Type: text/plain; charset="utf-8"\nSubject: Warning from ITS VPN server to ${CN}\nДо окончания срока действия сертификата (VPN) удалённого доступа осталась одна неделя." | sendmail -F${HOSTNAME} ${emailAddress} ${MAILADM}
echo "${DCURR} ${CN} AWEEK" >> ${LOG}
fi
else
if [ ${DEXP} -lt ${AMONTH} ]
then
if [ "`cat ${LOG} | grep -i ${CN} | grep -i AMONTH`" == "" ] || [ `cat ${LOG} | sort --reverse | grep -i ${CN} | grep -i --max-count=1 AMONTH | awk '{print $1}'` -lt ${DFROM} ]
then
echo -e "Content-Type: text/plain; charset="utf-8"\nSubject: Warning from ITS VPN server to ${CN}\nДо окончания срока действия сертификата (VPN) удалённого доступа остался один месяц." | sendmail -F${HOSTNAME} ${emailAddress} ${MAILADM}
echo "${DCURR} ${CN} AMONTH" >> ${LOG}
fi
fi
fi
fi
done
exit 0
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
HOSTNAME=`cat /etc/hostname`
MAILADM=support@vpn.example.local
# Указываем месторасположение файлов сертификатов
KEYS=/etc/openvpn/easy-rsa/keys/
# Указываем имя и местораположение индекса используемых сервером сертификатов
INDEX=/etc/openvpn/easy-rsa/keys/index.txt
# Указываем имя и месторасположение индекса рассылки
LOG=/var/log/openvpn/check-expare.log
# Задаём временные метки для инициирования высылки уведомления
AMONTH=2678400
AWEEK=604800
ATREEDAY=259200
# Запускаем перебор строк файла индекса (отрабатываем только задействованные, не отозванные)
cat $INDEX | grep '^V' | while read LINE
do
# Получаем имя сертификата
CN=`echo $LINE | awk 'match($0,/\/CN=.+\//) {print substr($0, RSTART, RLENGTH)}' | cut -c 5- | rev | cut -c 5- | rev`
# Получаем адрес электронного почтового ящики, на который будем слать уведомления
emailAddress=`echo $LINE | awk 'match($0,/\/emailAddress=.+/) {print substr($0, RSTART, RLENGTH)}' | cut -c 15- | rev | cut -c 1- | rev`
# Получаем дату начала действия сертификата
DFROM=`cat ${KEYS}/${CN}.crt | grep -i "Not Before" | awk 'match($0,/: .+/) {print substr($0, RSTART, RLENGTH)}' | cut -c 3- | rev | cut -c 1- | rev`
# Получаем дату окончания действия сертификата
DTO=`cat ${KEYS}/${CN}.crt | grep -i "Not After" | awk 'match($0,/: .+/) {print substr($0, RSTART, RLENGTH)}' | cut -c 3- | rev | cut -c 1- | rev`
# Приводим значения полученных дат к единому образцу - времени, прошедшему от начала "эпохи" UNIX (seconds since 1970-01-01 00:00:00 UTC)
DCURR=`date +%s`
DFROM=`date --date="${DFROM}" +%s`
DTO=`date --date="${DTO}" +%s`
# Вычисляем, сколько секунд осталось до окончания действия сертификата
DEXP=`expr ${DTO} - ${DCURR}`
# Проверяем, не настало-ли время
if [ ${DEXP} -lt ${ATREEDAY} ]
then
# Если событие по сроку информирования для проверяемого сертификата не зафиксировано, то делаем это
if [ "`cat ${LOG} | grep -i ${CN} | grep -i ATREEDAY`" == "" ] || [ `cat ${LOG} | sort --reverse | grep -i ${CN} | grep -i --max-count=1 ATREEDAY | awk '{print $1}'` -lt ${DFROM} ]
then
# Высылаем уведомление на адрес электронной почты, указанный при создании сертификата
echo -e "Content-Type: text/plain; charset="utf-8"\nSubject: Warning from ITS VPN server to ${CN}\nДо окончания срока действия сертификата (VPN) удалённого доступа осталось три дня." | sendmail -F${HOSTNAME} ${emailAddress} ${MAILADM}
# Записываем в журнал событие
echo "${DCURR} ${CN} ATREEDAY" >> ${LOG}
fi
else
if [ ${DEXP} -lt ${AWEEK} ]
then
if [ "`cat ${LOG} | grep -i ${CN} | grep -i AWEEK`" == "" ] || [ `cat ${LOG} | sort --reverse | grep -i ${CN} | grep -i --max-count=1 AWEEK | awk '{print $1}'` -lt ${DFROM} ]
then
echo -e "Content-Type: text/plain; charset="utf-8"\nSubject: Warning from ITS VPN server to ${CN}\nДо окончания срока действия сертификата (VPN) удалённого доступа осталась одна неделя." | sendmail -F${HOSTNAME} ${emailAddress} ${MAILADM}
echo "${DCURR} ${CN} AWEEK" >> ${LOG}
fi
else
if [ ${DEXP} -lt ${AMONTH} ]
then
if [ "`cat ${LOG} | grep -i ${CN} | grep -i AMONTH`" == "" ] || [ `cat ${LOG} | sort --reverse | grep -i ${CN} | grep -i --max-count=1 AMONTH | awk '{print $1}'` -lt ${DFROM} ]
then
echo -e "Content-Type: text/plain; charset="utf-8"\nSubject: Warning from ITS VPN server to ${CN}\nДо окончания срока действия сертификата (VPN) удалённого доступа остался один месяц." | sendmail -F${HOSTNAME} ${emailAddress} ${MAILADM}
echo "${DCURR} ${CN} AMONTH" >> ${LOG}
fi
fi
fi
fi
done
exit 0
Вот и всё, в общем-то. Созданный нами скрипт должен запускаться периодически. Думаю, что одного раза в сутки, с утра, будет достаточно. Размещаем команду запуска скрипта в таблице /etc/crontab:
# cat /etc/crontab
....
30 6 * * * openvpn /etc/custom/openvpn/check-expare.sh &
....
30 6 * * * openvpn /etc/custom/openvpn/check-expare.sh &
....