#!/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 " 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 -----"