This commit is contained in:
Gilles Mouchet 2025-09-11 20:29:10 +02:00
parent 08b7356179
commit ed2bbbbe0c
6 changed files with 398 additions and 93 deletions

View File

@ -1,21 +1,37 @@
# Project Name
TODO: Write a project description
This script checks the validity of a certificate and renews it if necessary
## Requirements
TODO: Requirments
A pki on <pki_path>/\<domain>
## Installation
TODO: Describe the installation process
```bash
sudo ./install.sh
```
A cron file is created
## Parameters
See `/etc/renew-cert/renew-cert.conf`
## Usage
TODO: Write usage instructions
```bash
./renew-cert.sh --help
```
```bash
Usage: ./renew-cert.sh 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
./renew-cert.sh --domain gmolab.net
```
### Changelog
### [1.0.0] - 2025-09-06
### [1.0.0] - 2025-09-11
#### Added
- New features and functionality.
#### Modified
- Changes to existing functionality (backwards compatible).
#### Fixed
- Bug fixes.
#### Removed
- Deprecated or removed features (breaking changes).
- check expiration date certificate
- renew certification
- send mail
#### Project initialization
- initialization by [GMo](mailto:gilles.mouchet@gmail.com)

View File

@ -37,17 +37,21 @@ installPackage() {
#-----------------------------------------------------------
# variables
user=gilles
group=gilles
fullScriptName=renew-cert.sh
shortScriptName=`echo $fullScriptName | sed -e 's|.*/||g' | cut -f1 -d.`
destPath=/usr/local/bin/
destPath=/usr/local/bin/gmotools
configFile=$shortScriptName.conf
configFilePath=/etc/$shortScriptName/
logRotateFile=$shortScriptName
logRotateFilePath=/etc/logrotate.d/$logRotateFile
cronFile=$shortScriptName.cron
# 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."
echo "[ERROR] - this script must be run as root or with sudo."
exit 1
fi
@ -58,18 +62,18 @@ if command -v apt &> /dev/null; then
elif command -v dnf &> /dev/null; then
packageManager="dnf"
else
echo "Erreur : No supported package managers (apt, dnf) were found."
echo "[ERROR] - no supported package managers (apt, dnf) were found."
exit 1
fi
echo "Package manager detected: $packageManager"
echo "[INFO] - package manager detected: $packageManager"
# check if logPath exist
if [ ! -d $configFilePath ]; then
mkdir $configFilePath &> /dev/null
rc=$?
if [ "$rc" != "0" ];then
echo "[ERROR] - An error occurred while creating $configFilePath ($rc)"
else echo "[SUCCESS] - The folder $configFilePath was created successfully."
echo "[ERROR] - an error occurred while creating $configFilePath ($rc)"
else echo "[SUCCESS] - the folder $configFilePath was created successfully."
fi
fi
# install package (example)
@ -79,22 +83,51 @@ installPackage mutt &> /dev/null
cp $fullScriptName $destPath/. &> /dev/null
rc=$?
if [ "$rc" != "0" ];then
echo "[ERROR] - An error occurred while copying $fullScriptName to $destPath ($rc)"
else echo "[SUCCESS] - The script ${fullScriptName} to $destPath was copied successfully."
echo "[ERROR] - an error occurred while copying $fullScriptName to $destPath ($rc)"
exit 1
else echo "[SUCCESS] - the script ${fullScriptName} to $destPath was copied successfully."
fi
# copy config file
cp $configFile $configFilePath &> /dev/null
rc=$?
if [ "$rc" != "0" ];then
echo "[ERROR] - An error occurred while copying $configFile to $configFilePath ($rc)"
else echo "[SUCCESS] - The script $configFile to $configFilepath was copied successfully."
echo "[ERROR] - an error occurred while copying $configFile to $configFilePath ($rc)"
exit 1
else echo "[SUCCESS] - the script $configFile to $configFilepath was copied successfully."
fi
cp $logRotateFile.logrotate $logRotateFilePath &> /dev/null
rc=$?
if [ "$rc" != "0" ];then
echo "[ERROR] - An error occurred while copying $logRotateFile.logrotate to $logRotateFilePath ($rc)"
else echo "[SUCCESS] - The script $logRotateFile.logrotate to $logRotateFilePath was copied successfully."
echo "[ERROR] - an error occurred while copying $logRotateFile.logrotate to $logRotateFilePath ($rc)"
exit 1
else echo "[SUCCESS] - the script $logRotateFile.logrotate to $logRotateFilePath was copied successfully."
fi
echo "Installation completed."
cp $shortScriptName.cron /etc/cron.d/$shortScriptName &> /dev/null
rc=$?
if [ "$rc" != "0" ];then
echo "[ERROR] - n error occurred while copying $shortScriptName.cron to /etc/cron.d/$shortScriptName ($rc)"
exit 1
else echo "[SUCCESS] - $shortScriptName.cron to /etc/cron.d/$shortScriptName was copied successfully."
fi
# create log file if not exist
if [ ! -d /var/log/$shortScriptName ]; then
mkdir /var/log/$shortScriptName &> /dev/null
rc=$?
if [ "$rc" != "0" ];then
echo "[ERROR] - An error occurred while creating /var/log/$shortScriptName ($rc)"
exit 1
else echo "[SUCCESS] - /var/log/$shortScriptName was created successfully."
fi
fi
sudo chown $user:$group /var/log/$shortScriptName
rc=$?
if [ "$rc" != "0" ];then
echo "[ERROR] - An error occurred while applying user ($user) and group ($group) owner /var/log/$shortScriptName ($rc)"
exit 1
else echo "[SUCCESS] - User ($user) and group ($group) owner on /var/log/$shortScriptName was applied successfully."
fi
echo "Installation completed"

View File

@ -1,3 +1,47 @@
# mail recipient
msgRecipient=exploit.gmotech@gmail.com
#onScreen mode - display message log on screen
# 0 no display log on screen
# 1 display log entry on screen
onScreen=0
# debug mode - display more var value
#. 0 disable debug mode
# 1 enable debug mode
debug=0
# folder where the root of the domain PKI is located
pkiRootPath=/home/gilles/certs
# credentials file for the domain certificate .key file
credFilePath=/home/gilles
# number of days the certificate is valid upon renewal
certDaysValidity=30
# warning message sent x days
# before the end of the certificate validity
warningDays=7
# critical message sent x days
# before the end of the certificate validity
criticalDays=3
# certificate renewal x days before
# before the end of the certificate validity
renewDays=1
# send warning mail
warningMail=1
# send critical mail
criticalMail=1
# send renewcert mail
renewMail=1
# send info mail
#if 1 a message is sent each time the file is executed
#even if there is no error
infoMail=0
# mail recipient
msgRecipient=exploit.gmotech@gmail.com

3
renew-cert.cron Normal file
View File

@ -0,0 +1,3 @@
# there are no rediect /dev/null. It's normal
# if redirect not input in log file
01 00 * * * gilles /usr/local/bin/gmotools/renew-cert.sh -d gmolab.net

View File

@ -1,8 +1,8 @@
/var/log/template/template.log {
/var/log/renew-log/renew-log.log {
daily
rotate 7
compress
missingok
notifempty
create 644 root root
create 644 gilles gilles
}

View File

@ -1,8 +1,8 @@
#!/bin/bash
############################################################
# Decription: Template script
# Decription: Renew certificate
# Author: Gilles Mouchet (gilles.mouchet@gmail.com)
# Creation Date: 06-Sep-2025
# Creation Date: 11-Sep-2025
# Version: 1.0.0
#
# Changelog:
@ -11,16 +11,23 @@
# - 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\nTemplate script $version by Exploit GMoTech"
tmpFile=/tmp/list.txt
mailFooter="\n\n$progName script V$version on `hostname` by Exploit GMoTech"
tmpFile=/tmp/$progName.log
#-----------------------------------------------------------
# FUNCTIONS
@ -28,14 +35,64 @@ tmpFile=/tmp/list.txt
function usage() {
cat << EOF
Usage: ./$(basename "$0") options
Template script
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
@ -48,12 +105,7 @@ function sendMail() {
# parameter
# $1 define entry type (info, warning, error)
# $2 define text
# $3 define display on screen or not (nothing=no, 1=yes)
function log() {
if [ -z "$3" ]; then
displayScreen=0
else displayScreen=1
fi
case "$1" in
I)
logType="[info]"
@ -62,35 +114,49 @@ function log() {
logType="[warning]"
;;
E)
logType="[error]"
;;
logType="[error]"
;;
C)
logType="[critical]"
;;
D)
logType="[debug]"
;;
esac
# on screen and logfile
#echo "$(date "+%Y-%m-%d")-$(date "+%H:%M:%S") - $logType - $2" | tee -a "$logFile"
#echo "[$(date "+%Y-%m-%d")-$(date "+%H:%M:%S")] - $logType - $2" >> "$logFile"
# true to display screen to
if [ "${displayScreen}" -eq 1 ];then
echo "[$(date "+%Y-%m-%d")-$(date "+%H:%M:%S")] - $logType - $2" | tee -a "$logFile"
else
# 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
# 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
#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
@ -98,24 +164,38 @@ if [ ! -f $cfgFile ]; then
exit 1
fi
# read config file
. $cfgFile
log I "script start" 1
log I "----- script start -----"
# check if logPath exist
if [ ! -d $logPath ]; then
mkdir $logPath
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
# exit
#fi
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
@ -130,46 +210,175 @@ Defined in script
-------------------------------------------------------------------------------
Defined in $cfgFile
-------------------------------------------------------------------------------
message recipient: $msgRecipient
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
exit
endScript
;;
version|-v|--version)
-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
exit
endScript
;;
# must be in the last block of the case because of *
*|help|-h|--help)
*|help|-h|--help)
log I "script run with -h, --help option"
usage
exit
endScript
;;
esac
shift
done
# success message
log I "send a success message" 1
mailSubject="[SUCCESS] - script result on `hostname`"
mailBody=" This is a success test mail\nHave a good day"
sendMail
# check if pki folder and pki files for domain
fullpkiRootPath="$pkiRootPath/`echo $certFile | sed -e 's|.*/||g' | cut -f1 -d.`"
# warnig message
log W "send a warning message" 1
mailSubject="[WARNING] - script result on `hostname`"
mailBody=" This is a warning test mail\nHave a good day"
sendMail
# check if backupcrtpath exist
if [ ! -d "$fullpkiRootPath/backup" ]; then
mkdir $fullpkiRootPath/backup
fi
# error message
log E "send an error message" 1
cat << EOF > $tmpFile
This file contain the description error
or log file
EOF
mailSubject="[ERROR] - script result on `hostname`"
mailBody=" This is a warning test mail\nHave a good day"
sendMail
rm -rf $tmpFile
# 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 -----"