| Current Path : /home/jeromecohp/www/aesecure/pro/crontab/ |
| Current File : /home/jeromecohp/www/aesecure/pro/crontab/aesecure.sh |
#!/bin/bash
# -------------------------------------------------------------------------------------------------------------------------------
# aesecure v2.0 - aeSecure (c) 2014-2015 Christophe Avonture
#
# Scan a folder recursively and list every files that have been modified during the last 60 minutes. Send a notification email
# if such files are found.
#
# This script shouldn't be altered.
#
# Initialization should be done in the aesecure.json file that is shipped with this script and should be placed in the same folder.
# Open aesecure.json and update its content to fit your needs.
#
# Once done, add a job in your cron and schedule this script to be fired every hour. Be sure to synchronize the duration
# (in the json file (in minutes)) and your cronjob. The two value should be the same
#
# -------------------------------------------------------------------------------------------------------------------------------
# -----------------------------------------------------------------------------------------------------------------------------
# Initialize variables
# -----------------------------------------------------------------------------------------------------------------------------
function initialize {
# Root folder and his child, logs
ROOTFOLDER="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TEMPLATESFOLDER=$ROOTFOLDER/"templates/"
LOGFOLDER=$ROOTFOLDER/"logs/"
# Retrieve the full name of this script.
SCRIPT_FULLNAME=$ROOTFOLDER/`basename "${BASH_SOURCE[0]}"`
# Script name (only the name, without folder and extension)
SCRIPT=`basename $0 | sed 's/.sh//'` #`echo "${BASH_SOURCE[0]}" | sed 's/.sh//'`
# Associated json
JSON=$ROOTFOLDER/$SCRIPT".json"
# Read the json configuration and initialize variables
# http://www.experts-exchange.com/Programming/Languages/Regular_Expressions/Q_27568762.html
json=`cat $JSON` # Get file content into a memory variable
SERVER=`echo $json | sed -e 's/^.*"server"[ ]*:[ ]*"//' -e 's/".*//'` # Extract the server (f.i. avonture.be)
TIMEZONE=`echo $json | sed -e 's/^.*"timezone"[ ]*:[ ]*"//' -e 's/".*//'` # Extract the timezone (f.i. EUROPE/Brussels)
RECIPIENT=`echo $json | sed -e 's/^.*"recipient"[ ]*:[ ]*"//' -e 's/".*//'` # Extract the email recipient (people who'll receive an email notification when files are modified)
HOMEDIR=`echo $json | sed -e 's/^.*"homedir"[ ]*:[ ]*"//' -e 's/".*//'` # Extract the homedir (f.i. /home/myuser/public_html); root folder from where the search will start
HOMEDIR="${HOMEDIR//\\/}" # Due to json encoding, the / directory separator is encoded as \/ so remove the / part.
TMPDIR=`echo $json | sed -e 's/^.*"tmpdir"[ ]*:[ ]*"//' -e 's/".*//'` # Extract the location of the temporary folder (f.i. /home/myuser/tmp)
TMPDIR="${TMPDIR//\\/}" # Due to json encoding, the / directory separator is encoded as \/ so remove the / part.
DURATION=`echo $json | sed -e 's/^.*"crontab_duration"[ ]*:[ ]*"//' -e 's/".*//'` # Extract the duration (in minutes) for the tracking
SENDMAIL=`echo $json | sed -e 's/^.*"sendmail"[ ]*:[ ]*"//' -e 's/".*//'` # Does the script send a notification by email ?
SAVELOGS=`echo $json | sed -e 's/^.*"savelogs"[ ]*:[ ]*"//' -e 's/".*//'` # Does the script save logs ?
CLEANAFTER=`echo $json | sed -e 's/^.*"cleanafter"[ ]*:[ ]*"//' -e 's/".*//'` # Remove old logs and backup after xxxx days.
# Actions
RUN_IOFILESMOD=`echo $json | sed -e 's/^.*"ioFilesMod"[ ]*:[ ]*"//' -e 's/".*//'` # Should we fire the script "Get files modified the last xxx minutes" ?
RUN_DBUSERSLIST=`echo $json | sed -e 's/^.*"dbUsersList"[ ]*:[ ]*"//' -e 's/".*//'` # Should we fire the script "Get the list of users created in the database during the last xxx minutes" ?
RUN_DBBACKUP=`echo $json | sed -e 's/^.*"dbBackup"[ ]*:[ ]*"//' -e 's/".*//'` # Should we fire the script "Make DB Backup" ?
# ioFilesMod
IO_FILEMOD_FOLDERS=`echo $json | sed -e 's/^.*"folders"[ ]*:[ ]*"//' -e 's/".*//' | tr '@' '|'` # Extract the list of folders to ignore (f.i. /cache/ and /temp/); this as a regular expression
IO_FILEMOD_FILES=`echo $json | sed -e 's/^.*"files"[ ]*:[ ]*"//' -e 's/".*//' | tr '@' '|'` # Extract the list of files to ignore (f.i. *.log, *.tmp, ...); this as a regular expression
# Database
DBHOST=`echo $json | sed -e 's/^.*"dbhost"[ ]*:[ ]*"//' -e 's/".*//'` # Database host (f.i. localhost)
DBNAME=`echo $json | sed -e 's/^.*"dbname"[ ]*:[ ]*"//' -e 's/".*//'` # Database name
DBUSER=`echo $json | sed -e 's/^.*"dbuser"[ ]*:[ ]*"//' -e 's/".*//'` # Database username
DBPWD=`echo $json | sed -e 's/^.*"dbpwd"[ ]*:[ ]*"//' -e 's/".*//'` # Database password
DBPREFIX=`echo $json | sed -e 's/^.*"dbprefix"[ ]*:[ ]*"//' -e 's/".*//'` # Database table prefix
DBBACKUPDIR=`echo $json | sed -e 's/^.*"backupdir"[ ]*:[ ]*"//' -e 's/".*//'` # Folder where to store databases's backup
DBBACKUPDIR="${DBBACKUPDIR//\\/}" # Due to json encoding, the / directory separator is encoded as \/ so remove the / part.
LASTRUNFILE=$ROOTFOLDER"/_lastrun.log" # Lastrun file
# Be sure that the LOGFOLDER exists otherwise use temp
if [ ! -d "$LOGFOLDER" ]; then mkdir "$LOGFOLDER"; fi
# Set the timezone for this script so date/hours will be correctly displayed
export TZ=$TIMEZONE
}
# -----------------------------------------------------------------------------------------------------------------------------
# Debug function - Display variables
# -----------------------------------------------------------------------------------------------------------------------------
function dump_variables {
clear
echo ""
echo "##############################################"
echo "# aeSecure - Bash script - List of variables #"
echo "##############################################"
echo ""
echo "Script variables:"
echo "================="
echo ""
echo "Script = $SCRIPT"
echo "Script fullname = $SCRIPT_FULLNAME"
echo "Root folder = $ROOTFOLDER"
echo "Templates folder = $TEMPLATESFOLDER"
echo "Log folder = $LOGFOLDER"
echo "JSON file = $JSON"
echo ""
echo "Configuration (from json):"
echo "=========================="
echo ""
echo "Server = $SERVER"
echo "Timezone = $TIMEZONE"
echo "Duration = $DURATION minutes"
echo "Home directory = $HOMEDIR"
echo "Temporary directory = $TMPDIR"
echo "Save logs = $SAVELOGS"
echo "Remove logs/backups afer = $CLEANAFTER days"
echo "Send email notification = $SENDMAIL"
echo "Mail recipient = $RECIPIENT"
echo ""
echo "Action to fire"
echo "--------------"
echo "Get files modified the last xxx min. = $RUN_IOFILESMOD"
echo "Get the list of users created the last xxx min. = $RUN_DBUSERSLIST"
echo "Make DB Backup = $RUN_DBBACKUP"
echo ""
echo "Filesmod - settings"
echo "-------------------"
echo "Exceptions - Folders = $IO_FILEMOD_FOLDERS"
echo "Exceptions - Files = $IO_FILEMOD_FILES"
echo ""
echo "Database - settings"
echo "-------------------"
echo "Host = $DBHOST"
echo "DBName = $DBNAME"
echo "UserName = $DBUSER"
echo "Password = $DBPWD"
echo "TablePrefix = $DBPREFIX"
echo "Backup folder = $DBBACKUPDIR"
echo ""
echo ""
}
# -----------------------------------------------------------------------------------------------------------------------------
# Get the LastRun Date of this script
# -----------------------------------------------------------------------------------------------------------------------------
function getLastRunDate {
# The _lastrun file isn't found ==> create the file and start the backup. Important : use printf to avoid carriage return
if [ ! -f $LASTRUNFILE ]; then printf "1800-0-0 00:00" > $LASTRUNFILE; fi
LASTRUN=`cat $LASTRUNFILE`
# Split the LASTRUN date/time into two variables
LASTRUNDATE=$(echo $LASTRUN | awk -F" " '{ print $1 }')
LASTRUNTIME=$(echo $LASTRUN | awk -F" " '{ print $2 }')
echo $LASTRUNDATE;
}
# -----------------------------------------------------------------------------------------------------------------------------
# Scan the HOMEDIR and find files with a modification file date (of creation file date) that is less than ... (f.i. 60 minutes)
# If found, create a logfile and return a full HTML string
# -----------------------------------------------------------------------------------------------------------------------------
function findFilesModifications {
FCT="ioFilesMod"
# Check : the HOMEDIR variable can't be empty. This variable should point to the root folder where the scan should start
ERRORMSG="":
if [ -z "$HOMEDIR" ]; then
ERRORMSG="<tr><td colspan='5' style='color:red;font-weight:bold'>The aesecure.json file is incorrect, the homedir configuration setting is empty. $ROOTFOLDER has been used...</td></tr>";
HOMEDIR=$ROOTFOLDER;
fi
# Temporary file with the list of files that have been modified
if [ $SAVELOGS -eq 1 ]; then
# Check if the folder LOG/filemod/ folder exists; if not, create it
if [ ! -d "$LOGFOLDER$FCT/" ]; then mkdir $LOGFOLDER$FCT; fi
CHANGES=$LOGFOLDER$FCT"/`date +"%Y-%m-%d_%H:%M"`.txt"
else
CHANGES=$TMPDIR$FCT".txt"
fi
# Be sure that this temporary file isn't already present (old run)
rm -f $CHANGES
# Find all files that have been modified during the last $DURATION minutes
# Exclude a folder that are specified in $IO_FILEMOD_FOLDERS; like the cache or temp folders
find $HOMEDIR -type f -mmin -$DURATION -name "*" -exec ls -l {} \; | grep -v -E "$IO_FILEMOD_FOLDERS" > $CHANGES
# Return the list of changes; if any
if [ -s $CHANGES ]; then
# Store the content of the file in the input variable
input=$CHANGES
i=0
# Initialize the result string to the error msg if any (to an empty string otherwise)
RESULT=$ERRORMSG;
# Process the file line by line to determine if we need to monitor the change or not
while read chmod tmp1 tmp2 tmp3 filesize month day hour filename
do
# Continue only if the regex isn't matched i.e. if the filename shouldn't be skipped (i.e. matching the IO_FILEMOD_FILES regex)
if ! [[ $filename =~ $IO_FILEMOD_FILES ]]
then
# The file shouldn't be skipped.
# Add this file in the result string that will then be sent by email
bFound=1
i=$((i+1));
# The filename can be long like /home/myuser/public_html/website1/...
# Since the HOMEDIR (/home/myuser/public_html/) is always the same; don't repeat it again and again. Keep filenames as shortest as possible.
# Substitute /home/myuser/public_html/ by an empty string
filename="${filename/$HOMEDIR\///}"
RESULT=$RESULT"<tr><td class='nbr'>$i</td><td class='lastmod'>$month $day $hour</td><td class='chmod'>$chmod</td><td class='filename'>$filename</td><td class='filesize'>$filesize</td></tr>"
fi
done < "$input"
# Check if $i is equal to 0. If not, we've found at least one file; send a notification email.
if ! [[ $i -eq 0 ]]; then
if [[ $i -eq 1 ]]; then INTRO="1 file has"; else INTRO="$i files have"; fi
# Get the HTML mail template (the filename is templates/filesmod.aec i.e. the same filename that this current script; located in the same folder than
# the current script but with .aec as file's extension (instead of .sh)
HTML=`echo $TEMPLATESFOLDER$FCT.aec`
# The template contains a lot of variables like HOMEDIR, SERVER, DURATION, ... Replace all occurences of these variables
# with the adhoc variable
TMP=`cat $HTML`
TMP="${TMP//INTRO/$INTRO}"
TMP="${TMP//RESULT/$RESULT}"
echo $TMP
# Delete files older than xxx days (see $CLEANAFTER)
find $(dirname ${CHANGES})/* -mtime +"$CLEANAFTER" -exec rm {} \;
fi
else
# No changes found
echo "";
fi
# Delete all files of 0 bytes. This is the case when the "find" instruction here above return nothing; the file is well created with 0 byte
find $(dirname ${CHANGES})/* -size 0 -delete
}
# -----------------------------------------------------------------------------------------------------------------------------
# Get the list of users added in the database recently and send an email
# -----------------------------------------------------------------------------------------------------------------------------
function dbLastCreatedUsers {
FCT="dbUsersList"
# Run the check
LASTRUNDATE=$(getLastRunDate);
DATE=$(date +"%Y-%m-%d")
# If $LASTRUNDATE is not equal to $DATE; it means that the lastrun wasn't yet done today => get the list of users
if [ ! "$DATE" == "$LASTRUNDATE" ]; then DOIT=1; else DOIT=0; fi
if [ $DOIT -eq 1 ]; then
if ([ -z "$DBHOST" ] || [ -z "$DBNAME" ] || [ -z "$DBUSER" ]); then
echo "aesecure.sh - $FCT ERROR : The configuration file is incorrect; at least one of these configuration setting is missing : database server, database name or database user. If you are not using a database, please disable the check for the last added users in your database.";
else
# Get the SQL file for getting the list of last created users
sSQL=`echo $TEMPLATESFOLDER"$FCT.sql"`
# Read the file and replace the variable DBPREFIX with the table's prefix to use
SQL=`cat $sSQL`
SQL="${SQL//DBPREFIX/$DBPREFIX}"
# Get the list of users created during the last xxx minutes (f.i. the last 60 minutes)
SQL="${SQL//DURATION/$DURATION}"
# Temporary file with the list of files that have been modified
if [ $SAVELOGS -eq 1 ]; then
# Check if the folder LOG/filemod/ folder exists; if not, create it
if [ ! -d "$LOGFOLDER$FCT/" ]; then mkdir $LOGFOLDER$FCT; fi
CHANGES=$LOGFOLDER$FCT"/`date +"%Y-%m-%d_%H:%M"`.html"
else
CHANGES=$TMPDIR$FCT".html"
fi
echo $(date +"%Y-%m-%d %H:%M") > $LASTRUNFILE;
# Run the query and output the result in the dbUsersList.txt file
mysql -D$DBNAME -u$DBUSER -p$DBPWD -e "$SQL" --html > $CHANGES
# Delete all files of 0 bytes.
find $(dirname ${CHANGES})/* -size 0 -delete
if [ -s $CHANGES ]; then
# Get the list of users from the file
RESULT=`cat $CHANGES`
# Remove the <table> and </table> tags; already present in the template
RESULT="${RESULT//<TABLE BORDER=1>/}"
RESULT="${RESULT//<\/TABLE>/}"
# Highlight some words
#RESULT="${RESULT//Premium+/<strong style='color:red;'>Premium+<strong>}"
#RESULT="${RESULT//Premium/<strong style='color:red;'>Premium<strong>}"
#RESULT="${RESULT//WebDeveloper/<strong style='color:red;'>WebDeveloper<strong>}"
# Get the HTML template and paste the list of users
HTML=`cat $TEMPLATESFOLDER$FCT.aec`
HTML="${HTML//RESULT/$RESULT}"
echo $HTML
# Delete files older than xxx days (see $CLEANAFTER)
find $(dirname ${CHANGES})/* -mtime +"$CLEANAFTER" -exec rm {} \;
else
# The query is empty; no record
echo ""
fi
fi # if ([ -z "$DBHOST" ]
else # if [ $DOIT -eq 1 ]
# The list of user has already be processed today
echo ""
fi # if [ $DOIT -eq 1 ]
}
# -----------------------------------------------------------------------------------------------------------------------------
# Get the list of users added in the database recently and send an email
#
# Warning : The backup will be done max. once by day : even if the job is scheduled every 60 minutes,
# a check will be done with the _lastrun.log file and backup will be done if the last run was prior to the execution date.
#
# -----------------------------------------------------------------------------------------------------------------------------
function dbBackup {
FCT="dbBackup"
# Check if the folder where to store DB Backup exists and if not, create it
if [ ! -d "$DBBACKUPDIR/" ]; then mkdir $DBBACKUPDIR; fi
LASTRUNDATE=$(getLastRunDate);
DATE=$(date +"%Y-%m-%d")
# If $LASTRUNDATE is not equal to $DATE; it means that the lastrun wasn't yet done today => make the backup
if [ ! "$DATE" == "$LASTRUNDATE" ]; then DOIT=1; else DOIT=0; fi
if [ $DOIT -eq 1 ]; then
if ([ -z "$DBHOST" ] || [ -z "$DBNAME" ] || [ -z "$DBUSER" ]); then
echo "aesecure.sh - $FCT ERROR : The configuration file is incorrect; at least one of these configuration setting is missing : database server, database name or database user. If you are not using a database, please disable the check for the last added users in your database.";
else # if ([ -z "$DBHOST" ]
# Make the backup once a day
mysqldump --user=$DBUSER --password=$DBPWD --host=$DBHOST $DBNAME > $DBBACKUPDIR/$DBNAME-$DATE.sql
# Compress the file and remove the uncompressed one
gzip -c $DBBACKUPDIR/$DBNAME-$DATE.sql > $DBBACKUPDIR/$DBNAME-$DATE.sql.gz
rm $DBBACKUPDIR/$DBNAME-$DATE.sql
echo $(date +"%Y-%m-%d %H:%M") > $LASTRUNFILE;
# Delete files older than xxx days (see $CLEANAFTER)
find $DBBACKUPDIR/* -mtime +"$CLEANAFTER" -exec rm {} \;
HTML=`cat $TEMPLATESFOLDER$FCT.aec`
HTML="${HTML//RESULT/$DBBACKUPDIR/$DBNAME-$DATE.sql.gz}"
echo $HTML
fi # if ([ -z "$DBHOST" ]
else
echo ""
fi
}
# ------------------------------------
# Send an email
#
# Parameters :
# #1 = Subject
# #2 = HTML mail body
# ------------------------------------
function sendMail {
# Check if the SendMail configuration item (from the JSON) allow to send emails
if [ $SENDMAIL -eq 1 ]; then
(
echo "From: $RECIPIENT "
echo "To: $RECIPIENT "
echo "MIME-Version: 1.0 "
echo "Content-Type: text/html "
echo "Content-Disposition: inline "
echo "Subject: aeSecure - $1 - server $SERVER"
# Replace generic variables
TMP="$2"
TMP="${TMP//SCRIPT_FULLNAME/$SCRIPT_FULLNAME}"
TMP="${TMP//HOMEDIR/$HOMEDIR}"
TMP="${TMP//SERVER/$SERVER}"
TMP="${TMP//DURATION/$DURATION}"
TMP="${TMP//TIMEZONE/$TIMEZONE}"
TMP="${TMP//DATE/`date`}"
TMP="${TMP//YEAR/`date +%G`}"
TMP="${TMP//DBNAME/$DBNAME}"
echo $TMP
) | /usr/sbin/sendmail -F $RECIPIENT
fi
}
# -----------
# Entry point
# -----------
# Initialize variables
initialize
#dump_variables
if [ $RUN_IOFILESMOD -eq 1 ]; then
# Get the list of files that have been modified on the server and if not empty, send an email with the list of changes
RESULT_FILESMOD=$(findFilesModifications)
if [ -n "$RESULT_FILESMOD" ]; then sendMail "File monitoring agent" "$RESULT_FILESMOD"; fi
fi
if [ $RUN_DBUSERSLIST -eq 1 ]; then
# Retrieve the list of last added users
RESULT_LASTUSERS=$(dbLastCreatedUsers)
if [ -n "$RESULT_LASTUSERS" ]; then sendMail "Database monitoring agent - List of recent added users" "$RESULT_LASTUSERS"; fi
fi
if [ $RUN_DBBACKUP -eq 1 ]; then
RESULT_DBBackup=$(dbBackup)
if [ -n "$RESULT_DBBackup" ]; then sendMail "Database backup agent - Daily backup done" "$RESULT_DBBackup"; fi
fi