385 lines
14 KiB
Bash
Executable File
385 lines
14 KiB
Bash
Executable File
#!/bin/bash
|
||
############################################################
|
||
# Decription: Renew certificate
|
||
# Author: Gilles Mouchet (gilles.mouchet@gmail.com)
|
||
# Creation Date: 11-Sep-2025
|
||
# Version: 1.0.0
|
||
#
|
||
# Changelog:
|
||
# V1.0.0 - 25-Sep-2025 - GMo
|
||
# Added
|
||
# - Creation of script from scratch
|
||
#
|
||
############################################################
|
||
#-----------------------------------------------------------------
|
||
# DON'T CHANGE ANYTHING FROM HERE
|
||
#-----------------------------------------------------------------
|
||
|
||
version="1.0.0"
|
||
# config
|
||
progName=`echo $0 | sed -e 's|.*/||g' | cut -f1 -d.`
|
||
confDir=/etc/$progName
|
||
cfgFile=$confDir/$progName.conf
|
||
logPath=/var/log/$progName
|
||
logFile=$logPath/$progName.log
|
||
# mail
|
||
mailSubject="[SUCCESS] - script result on `hostname`"
|
||
mailHeader="my_hdr From: GMO Check System <exploit.gmotech@gmail.com>"
|
||
mailBody=""
|
||
mailFooter="\n\n$progName script V$version on `hostname` by Exploit GMoTech"
|
||
tmpFile=/tmp/$progName.log
|
||
|
||
#-----------------------------------------------------------
|
||
# FUNCTIONS
|
||
#-----------------------------------------------------------
|
||
function usage() {
|
||
cat << EOF
|
||
Usage: ./$(basename "$0") options
|
||
Renew wilcard certificat
|
||
Options:
|
||
-d, --domain - domain name
|
||
-p, --param - display parameters
|
||
-h, --help - display this help
|
||
-v, --version - display script version
|
||
|
||
Example
|
||
Renew wildcard certificat for domain gmolab.net
|
||
./$(basename "$0") --domain gmolab.net
|
||
EOF
|
||
}
|
||
#-----------------------------------------------------------
|
||
function renewCertificate(){
|
||
log I "renew certificate"
|
||
log D "ca key file use $fullpkiRootPath/$caKeyFile"
|
||
log D "ca crt file use $fullpkiRootPath/$caCrtFile"
|
||
log D "ca csr file use $fullpkiRootPath/$certDomain.csr"
|
||
log D "bakup path file use $fullpkiRootPath/backup/"
|
||
# backup crt file
|
||
log I "copy $certFile to $fullpkiRootPath/backup/$certFile"
|
||
cp $fullpkiRootPath/$certFile $fullpkiRootPath/backup/$certFile-$(date +"%Y-%m-%d-%H-%M-%S") > $tmpFile
|
||
rc=$?
|
||
if [ "$rc" != "0" ];then
|
||
log I "send error message"
|
||
log E "a problem occurred while copying $certDomain certificate on $fullpkiRootPath/backup/$certFile ($rc)"
|
||
mailSubject="[ERROR] - a problem occurred while copying $certDomain certificate on $fullpkiRootPath/backup/$certFile ($rc)"
|
||
mailBody="Bad new!\n A problem occurred while copying $certDomain certificate on $fullpkiRootPath/backup/$certFile ($rc).\nHave a good day"
|
||
sendMail
|
||
endScript
|
||
fi
|
||
# renewal certificate
|
||
openssl x509 -req -in $fullpkiRootPath/$certDomain.csr \
|
||
-passin file:$caKeyCredFile \
|
||
-CA $fullpkiRootPath/$caCrtFile \
|
||
-CAkey $fullpkiRootPath/$caKeyFile \
|
||
-CAcreateserial \
|
||
-extfile $fullpkiRootPath/wilcard.cnf -out $fullpkiRootPath/$certFile \
|
||
-days $certDaysValidity -sha256 > $tmpFile 2>&1
|
||
rc=$?
|
||
if [ "$rc" != "0" ]; then
|
||
log I "send error message"
|
||
log E "a problem occurred while renewing $certDomain certificate ($rc)"
|
||
mailSubject="[ERROR] - a problem occurred while renewing $certDomain certificate ($rc)"
|
||
mailBody="Bad new!\n A problem occurred while renewing $certDomain certificate ($rc).\nHave a good day"
|
||
sendMail
|
||
rm -rf $tmpFile
|
||
else
|
||
endDateFo=$(openssl x509 -in $fullpkiRootPath/$certFile -noout -enddate | awk -F'=' '{print $2}' | xargs -I {} date -d "{}" '+%Y-%m-%d')
|
||
log I "certificate successfully renewed. New expiry date: $endDateFo"
|
||
log I "send a success mesaage"
|
||
mailSubject="[SUCCESS] - certificate for $certDomain successfully renewed. New expiry date: $endDateFo"
|
||
mailBody="Bad new!\n Certificate or $certDomain successfully renewed. New expiry date: $endDateFo.\nHave a good day"
|
||
sendMail
|
||
rm -rf $tmpFile
|
||
fi
|
||
}
|
||
#-----------------------------------------------------------
|
||
function sendMail() {
|
||
if [ -f "$tmpFile" ];then
|
||
echo -e "$mailBody $mailFooter" | mutt -e "$mailHeader" -s "${mailSubject}" $msgRecipient -a $tmpFile
|
||
else
|
||
echo -e "$mailBody $mailFooter" | mutt -e "$mailHeader" -s "${mailSubject}" $msgRecipient
|
||
fi
|
||
}
|
||
#-----------------------------------------------------------
|
||
# Function write log in file log
|
||
# parameter
|
||
# $1 define entry type (info, warning, error)
|
||
# $2 define text
|
||
function log() {
|
||
case "$1" in
|
||
I)
|
||
logType="[info]"
|
||
;;
|
||
W)
|
||
logType="[warning]"
|
||
;;
|
||
E)
|
||
logType="[error]"
|
||
;;
|
||
C)
|
||
logType="[critical]"
|
||
;;
|
||
D)
|
||
logType="[debug]"
|
||
;;
|
||
esac
|
||
|
||
# write all entries except [debug]
|
||
if [ "$logType" != "[debug]" ]; then
|
||
echo "[$(date "+%Y-%m-%d")-$(date "+%H:%M:%S")] - $logType - $2" >> "$logFile"
|
||
# display log entry on screen if onScreen is enabled
|
||
if [ "$onScreen" -eq 1 ];then
|
||
echo "[$(date "+%Y-%m-%d")-$(date "+%H:%M:%S")] - $logType - $2"
|
||
fi
|
||
fi
|
||
|
||
# write [debug] entries only if debug is enabled
|
||
if [ "$logType" == "[debug]" ] && [ "$debug" -eq 1 ]; then
|
||
echo "[$(date "+%Y-%m-%d")-$(date "+%H:%M:%S")] - $logType - $2" >> "$logFile"
|
||
# display log entry on screen if onScreen is enabled
|
||
if [ "$onScreen" -eq 1 ];then
|
||
echo "[$(date "+%Y-%m-%d")-$(date "+%H:%M:%S")] - $logType - $2"
|
||
fi
|
||
fi
|
||
|
||
}
|
||
#-----------------------------------------------------------
|
||
function endScript(){
|
||
log I "----- end script -----"
|
||
exit
|
||
}
|
||
#-----------------------------------------------------------
|
||
# MAIN
|
||
#-----------------------------------------------------------
|
||
|
||
# check if the effective user ID is 0 (root)
|
||
#if [[ $EUID -ne 0 ]]; then
|
||
# echo "This script must be run as root or with sudo."
|
||
# exit 1
|
||
#fi
|
||
|
||
# check if conf file or passphrase file exist
|
||
if [ ! -f $cfgFile ]; then
|
||
echo "$progName not installed correctly. Please run install.sh script"
|
||
exit 1
|
||
fi
|
||
|
||
# read config file
|
||
. $cfgFile
|
||
|
||
log I "----- script start -----"
|
||
|
||
# check if logPath exist
|
||
if [ ! -d $logPath ]; then
|
||
echo "$progName not installed correctly. Please run install.sh script"
|
||
endScript
|
||
fi
|
||
|
||
# check param exist. Uncomment if your script need parameters
|
||
if [ -z "$1" ]; then
|
||
usage
|
||
endScript
|
||
fi
|
||
|
||
while [[ "$#" -gt 0 ]]; do
|
||
case "$1" in
|
||
-d|--domain)
|
||
if [ -z "$2" ]; then
|
||
usage
|
||
endScript
|
||
else
|
||
certFile=$2.crt
|
||
certDomain=$2
|
||
log I "cert file $certFile"
|
||
fi
|
||
shift 2
|
||
;;
|
||
-p|--param)
|
||
log I "script run with -p or --param option"
|
||
cat << EOF
|
||
-------------------------------------------------------------------------------
|
||
Parameters
|
||
-------------------------------------------------------------------------------
|
||
Defined in script
|
||
-------------------------------------------------------------------------------
|
||
script name: $progName
|
||
config folder: $confDir
|
||
config file: $cfgFile
|
||
log path: $logPath
|
||
log file: $logFile
|
||
-------------------------------------------------------------------------------
|
||
Defined in $cfgFile
|
||
-------------------------------------------------------------------------------
|
||
message recipient: $msgRecipient
|
||
pki path: $pkiRootPath
|
||
display log on screen: $onScreen
|
||
debug mode: $debug
|
||
|
||
send warning mail
|
||
x days before
|
||
the end of validity: $warningDays
|
||
|
||
send critical mail
|
||
x days before
|
||
the end of validity: $criticalDays
|
||
|
||
certificate renewal
|
||
x days before
|
||
before the end of
|
||
the certificate validity: $renewDays
|
||
|
||
number of days
|
||
the certificate
|
||
is valid upon renewal: $certDaysValidity
|
||
|
||
sending an infor email: $infoMail
|
||
sending a warning email: $warningMail
|
||
sending a critical email: $criticalMail
|
||
sending a renewal email: $renewMail
|
||
EOF
|
||
endScript
|
||
;;
|
||
-v|--version)
|
||
log I "script run with -v or --verion option"
|
||
cat << EOF
|
||
$(basename "$0") v$version (c) 1990 - $(date +%Y) by Gilles Mouchet
|
||
Non-Commercial Use License – See LICENSE for details
|
||
EOF
|
||
endScript
|
||
;;
|
||
# must be in the last block of the case because of *
|
||
*|help|-h|--help)
|
||
log I "script run with -h, --help option"
|
||
usage
|
||
endScript
|
||
;;
|
||
esac
|
||
shift
|
||
done
|
||
|
||
# check if pki folder and pki files for domain
|
||
fullpkiRootPath="$pkiRootPath/`echo $certFile | sed -e 's|.*/||g' | cut -f1 -d.`"
|
||
|
||
# check if backupcrtpath exist
|
||
if [ ! -d "$fullpkiRootPath/backup" ]; then
|
||
mkdir $fullpkiRootPath/backup
|
||
fi
|
||
|
||
# set credFile and check if exist
|
||
caKeyCredFile=$credFilePath/.$certDomain
|
||
if [ ! -e "$caKeyCredFile" ]; then
|
||
log E "$caKeyCredFile doesn't exist !"
|
||
log I "send error message"
|
||
mailSubject="[ERROR] - $caKeyCredFile doesn't exist !"
|
||
mailBody="Oups !\n$caKeyCredFile doesn't exist !.\nHave a good day"
|
||
sendMail
|
||
endScript
|
||
fi
|
||
log I "cred file $caKeyCredFile"
|
||
|
||
# set CA file name
|
||
caCrtFile="`echo $certFile | sed -e 's|.*/||g' | cut -f1 -d.`CA.crt"
|
||
caKeyFile="`echo $certFile | sed -e 's|.*/||g' | cut -f1 -d.`CA.key"
|
||
log I "ca files $caCrtFile and $caKeyFile are used"
|
||
# check if cert exist
|
||
if [ ! -f "$fullpkiRootPath/$certFile" ] || [ ! -f "$fullpkiRootPath/$caCrtFile" ] || [ ! -f "$fullpkiRootPath/$caKeyFile" ]; then
|
||
log E "$certFile, $caCrtFile or $caKeyFile on $fullpkiRootPath doesn't exist."
|
||
log I "send error message"
|
||
mailSubject="[ERROR] - $certFile, $caCrtFile or $caKeyFile on $fullpkiRootPath doesn't exist"
|
||
mailBody="Problem !\nT$certFile, $caCrtFile or $caKeyFile on $fullpkiRootPath doesn't exist.\nHave a good day"
|
||
sendMail
|
||
endScript
|
||
fi
|
||
log I "all files are present on $fullpkiRootPath"
|
||
|
||
# set end cert expiration date an convert in timestamp
|
||
endDateFo=$(openssl x509 -in $fullpkiRootPath/$certFile -noout -enddate | awk -F'=' '{print $2}' | xargs -I {} date -d "{}" '+%Y-%m-%d')
|
||
endDateTs=$(date -d "$endDateFo" +%s)
|
||
|
||
# set current date and convert it in timestamp
|
||
currentDateFo=$(date "+%Y-%m-%d")
|
||
currentDateTs=$(date -d "$currentDateFo" +%s)
|
||
|
||
#--------------------------------------------------------------------------------------------------------------------
|
||
#FOR DEV
|
||
# set debug=1 and onScreen=1 in /etc/renew-cert/renew-cert.conf
|
||
#endDateFo="2025-11-14"
|
||
#endDateTs=$(date -d "$endDateFo" +%s)
|
||
#currentDateFo="2025-10-10"
|
||
#currentDateTs=$(date -d "$currentDateFo" +%s)
|
||
# END FOR DEV
|
||
#--------------------------------------------------------------------------------------------------------------------
|
||
|
||
# set the low and the hight threshold for warning message
|
||
warningMsgLowDateTs=$((endDateTs - (warningDays * 86400)))
|
||
warningMsgLowDateFo=$(date -d "@$warningMsgLowDateTs" "+%Y-%m-%d")
|
||
warningMsgHighDateTs=$((endDateTs - (criticalDays * 86400)- 86400))
|
||
warningMsgHighDateFo=$(date -d "@$warningMsgHighDateTs" "+%Y-%m-%d")
|
||
|
||
# set the low and the hight threshold for critical message
|
||
criticalMsgLowDateTs=$((endDateTs - (criticalDays * 86400)))
|
||
criticalMsgLowDateFo=$(date -d "@$criticalMsgLowDateTs" "+%Y-%m-%d")
|
||
criticalMsgHighDateTs=$((endDateTs - (renewDays * 86400)))
|
||
criticalMsgHighDateFo=$(date -d "@$criticalMsgHighDateTs" "+%Y-%m-%d")
|
||
|
||
# set the renewal dat
|
||
tmpNbrDaysTd=$((renewDays * 86400 ))
|
||
renewDateTs=$((endDateTs-tmpNbrDaysTd))
|
||
renewDateFo=$(date -d "@$renewDateTs" "+%Y-%m-%d")
|
||
|
||
# set number days before end today and expiration date
|
||
daysLeftTs=$((endDateTs-currentDateTs))
|
||
daysLeftFo=$((daysLeftTs / 86400))
|
||
|
||
daysPassTs=$((currentDateTs-endDateTs))
|
||
daysPassFo=$((daysPassTs / 86400))
|
||
|
||
log D "current date : $currentDateFo ($currentDateTs)" $onScreen
|
||
log D "certificate expiration date : $endDateFo ($endDateTs)" $onScreen
|
||
log D "nbr. of days before cert expires : $daysLeftFo ($daysLeftTs)" $onScreen
|
||
log D "warning mail will be send from $warningMsgLowDateFo ($warningMsgLowDateTs) to $warningMsgHighDateFo ($warningMsgHighDateTs)" $onScreen
|
||
log D "critical mail will be send from $criticalMsgLowDateFo ($criticalMsgLowDateTs) to $criticalMsgHighDateFo ($criticalMsgHighDateTs)" $onScreen
|
||
log D "certificate renew date to $renewDateFo ($renewDateTs)" $onScreen
|
||
|
||
# actions to do based on the number of days remaining
|
||
# Warning
|
||
if [ "$daysLeftFo" -le "$warningDays" ] && [ "$daysLeftFo" -gt "$criticalDays" ]; then
|
||
log W "the $certDomain certificate will expire in $daysLeftFo days ($endDateFo)."
|
||
if [ "$warningMail" -eq 1 ]; then
|
||
log I "send warning message"
|
||
mailSubject="[WARNING] - the $certDomain certificate will expire in $daysLeftFo days ($endDateFo)."
|
||
mailBody="Demands your attention!\nThe $certDomain certificate will expire in $daysLeftFo days ($endDateFo).\nHave a good day"
|
||
sendMail
|
||
fi
|
||
# critical
|
||
elif [ "$daysLeftFo" -le "$criticalDays" ] && [ "$daysLeftFo" -gt "$renewDays" ]; then
|
||
log C "the $certDomain certificate will expire in $daysLeftFo days ($endDateFo). Urgent renewal required."
|
||
if [ "$criticalMail" -eq 1 ]; then
|
||
log I "send critical message"
|
||
mailSubject="[CRITICAL] - the $certDomain certificate will expire in $daysLeftFo days ($endDateFo). Urgent renewal required."
|
||
mailBody="ATTENTION!\nThe $certDomain certificate will expire in $daysLeftFo days ($endDateFo). Urgent renewal required.\nHave a good day"
|
||
sendMail
|
||
fi
|
||
# renew
|
||
elif [ "$daysLeftFo" -eq "$renewDays" ]; then
|
||
log C "the '$certDomain' certificate expires in $daysLeftFo ($endDateFo) day. Renew immediately!"
|
||
renewCertificate
|
||
# expired
|
||
elif [ "$daysLeftFo" -le 0 ]; then
|
||
log C "the '$certDomain' certificate expired $daysPassFo ($endDateFo) days ago."
|
||
log I "send error message"
|
||
mailSubject="[CRITICAL] - the '$certDomain' certificate expired $daysPassFo ($endDateFo) days ago."
|
||
mailBody="Bad new !\nThe '$certDomain' certificate expired $daysPassFo ($endDateFo) days ago. \nHave a good day"
|
||
sendMail
|
||
else
|
||
# certificat ok
|
||
log I "the '$certDomain' certificate is valid. There are $daysLeftFo days left before expiration ($endDateFo)."
|
||
if [ "$infoMail" -eq 1 ]; then
|
||
log I "send info message"
|
||
mailSubject="[INFO] - the '$certDomain' certificate is valid. There are $daysLeftFo days left before expiration ($endDateFo)."
|
||
mailBody="All is ok!\nThe '$certDomain' certificate is valid. There are $daysLeftFo days left before expiration ($endDateFo).\nHave a good day"
|
||
sendMail
|
||
fi
|
||
fi
|
||
log I "----- end script -----"
|