#!/bin/bash # ____________________________________________________________________________ # # Copyright 2013 James Oakley, www.oakhosting.net # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # ____________________________________________________________________________ # ____________________________________________________________________________ # # This script automates downloading WAF mod_security rules from # atomicorp.com. It comes with no warranty, actual or implied. # It does NOT install these rules to start with. # Follow their documentation to create the necessary directories # # This script assumes the rules go in a modsec_rules directory within the # Apache configuration directory. Link to the ones you want in the main # file you use to set the mod_security configuration. # ____________________________________________________________________________ # ____________________________________________________________________________ # # -- Variables section -- # You need to set three variables for this script to work. # 1. The directory where the Apache configuration files are to be found # (The default value given is for a cPanel installation.) CONF_DIR=/usr/local/apache/conf # 2. Your username for the atomicorp.com website. # (This will be the username (not e-mail) you gave, usually lower-case) ASL_USERNAME={your-username-here} # 3. Your password for the atomicorp.com website. ASL_PASSWORD={your-password-here} # # ____________________________________________________________________________ # Now the script itself begins # Step 1: Retrieve the version number of the latest stable rules cd /usr/local/src echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Retrieving latest version number" wget --quiet --user=$ASL_USERNAME --password=$ASL_PASSWORD http://updates.atomicorp.com/channels/rules/subscription/VERSION echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Version number retrieved" # Step 2: Compare this retrieved version to the version of the existing rules installed # If there are no rules installed, or if there is no version file within them, new rules will be downloaded if [ -e VERSION ]; then source /usr/local/src/VERSION OLD_VERSION="n/a" if [ -e $CONF_DIR/modsec_rules/version.txt ]; then OLD_VERSION=$(cat $CONF_DIR/modsec_rules/version.txt) fi echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Old Version: $OLD_VERSION" echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- New Version: $MODSEC_VERSION" if [ "$OLD_VERSION" = "$MODSEC_VERSION" ]; then echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Version is unchanged - nothing to do" else # Step 3: If we need to download a new version, we download and then extract wget --quiet --user=$ASL_USERNAME --password=$ASL_PASSWORD http://updates.atomicorp.com/channels/rules/subscription/modsec-$MODSEC_VERSION.tar.gz if [ -e modsec-$MODSEC_VERSION.tar.gz ]; then tar -xzf modsec-$MODSEC_VERSION.tar.gz # Step 4: Back up the old rules # This is done by creating directories in the Apache configuration folder # These are named modsec_rules_bakN, and up to 4 old copies are retained echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Backing up old rules" if [ -e $CONF_DIR/modsec_rules_bak4 ]; then rm $CONF_DIR/modsec_rules_bak4 -rf fi if [ -e $CONF_DIR/modsec_rules_bak3 ]; then mv $CONF_DIR/modsec_rules_bak3 $CONF_DIR/modsec_rules_bak4 -f fi if [ -e $CONF_DIR/modsec_rules_bak2 ]; then mv $CONF_DIR/modsec_rules_bak2 $CONF_DIR/modsec_rules_bak3 -f fi if [ -e $CONF_DIR/modsec_rules_bak1 ]; then mv $CONF_DIR/modsec_rules_bak1 $CONF_DIR/modsec_rules_bak2 -f fi mkdir $CONF_DIR/modsec_rules_bak1 # Step 5: Move the old rules into the _bak1 directory # Then move the new rules into the modsec_rules directory # As we do so, we create a version file that contains the version number of these rules # This helps if support is needed from atomicorp. # This is also what we will use to avoid downloading the same version again later. mv $CONF_DIR/modsec_rules/* $CONF_DIR/modsec_rules_bak1 -f echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Moving new rules into place" mv modsec/* $CONF_DIR/modsec_rules echo $MODSEC_VERSION > $CONF_DIR/modsec_rules/version.txt # Step 6: Run Apache's configtest instruction, # to check that there are no errors in our configuration. # It's too risky to restart Apache without checking first. echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Testing Apache Configuration" APACHECHK=` /etc/init.d/httpd configtest 2>&1 | grep "Syntax OK"` if [[ $APACHECHK = "Syntax OK" ]]; then # Step 7: If there are no errors, we restart Apache. echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Restarting Apache" /etc/init.d/httpd restart echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Apache Restarted" echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Rules update completed" # Step 8: If there were errors, we use our backup directories to roll back # Note: If we had previously used all 4 _bakN directories, we will have lost # _bak4 in the process, but bak1_ to bak3_ will be as they were before. else echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Configuration Test Failed. Error follows:" /etc/init.d/httpd configtest 2>&1 echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Rolling Back" rm $CONF_DIR/modsec_rules -rf mv $CONF_DIR/modsec_rules_bak1 $CONF_DIR/modsec_rules -f if [ -e $CONF_DIR/modsec_rules_bak2 ]; then mv $CONF_DIR/modsec_rules_bak2 $CONF_DIR/modsec_rules_bak1 -f fi if [ -e $CONF_DIR/modsec_rules_bak3 ]; then mv $CONF_DIR/modsec_rules_bak3 $CONF_DIR/modsec_rules_bak2 -f fi if [ -e $CONF_DIR/modsec_rules_bak4 ]; then mv $CONF_DIR/modsec_rules_bak4 $CONF_DIR/modsec_rules_bak3 -f fi # Step 9: Run Apache's configtest to screen. # We do not restart Apache, but simply advise the user of the result of the test # There may be other reasons why Apache's configuration is broken. # If the rules update did not work, it is safer to leave Apache running while # the user checks what the issues were. echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Rerunning Apache Configuration Test" /etc/init.d/httpd configtest 2>&1 echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Rules updated failed" echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- APACHE HAS NOT BEEN RESTARTED. CHECK THE CONFIGTEST RESULT ABOVE BEFORE DOING SO" fi # Step 10: We print out the first 5 lines of modsec_rules # This allows the user to sanity-check the datestamps of the files # These should match the version number that has been downloaded. echo echo "`date +\%Y-\%m-\%d\ \%H:\%M:\%S` -- Start of modsec_rules directory follows for reference" ls $CONF_DIR/modsec_rules -l | head -n5 fi fi # Step 11: Remove the modsec download (if it was downloaded) rm -rf modsec modsec-$MODSEC_VERSION.tar.gz fi # Step 12: Remove the VERSION file and any sensitive environment variables rm -f /usr/local/src/VERSION unset ASL_USERNAME unset ASL_PASSWORD