UBUNTU24-CIS-Audit/run_audit.sh

214 lines
7.4 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#! /bin/bash
# script to run audit while populating local host data
# 13th Sept 2021 - Initial
# 9th Nov 2021 - Added root user check - more posix compliant for multiple OS types
# 10 Dec 2021 - Enhanced so more linux OS agnostic, less input required
# - added vars options for bespoke vars file
# - Ability to run as script from remediation role increased consistency
# 17 Dec 2021 - Added system_type variable - default Server will change to workstations with -w switch
# 02 Mar 2022 - Updated benchmark variable naming
# 06 Apr 2022 - Added format option in output inline with goss options e.g. json documentation this is for fault finding
# 03 May 2022 - update for audit variables improvement added by @pavloos - https://github.com/ansible-lockdown/RHEL8-CIS-Audit/pull/29
# 10 Jun 2022 - added format output for different type - supports json,documentation or rspecish
# 04 Oct 2022 - Changed default content location to /opt
# 14 Sep 2023 - Tidyup of code,
# linting (thanks to @cf-sewe)
# Oracle included by default if RHEL family
# benchmark vars moved
# December 2023 Added goss version and testing
# April 2024 Updating of OS discovery to work for all supported OSs
# Variables in upper case tend to be able to be adjusted
# lower case variables are discovered or built from other variables
# Goss benchmark variables (these should not need changing unless new release)
BENCHMARK=CIS # Benchmark Name aligns to the audit
BENCHMARK_VER=2.0.0
BENCHMARK_OS=UBUNTU24
# Goss host Variables
AUDIT_BIN="${AUDIT_BIN:-/usr/local/bin/goss}" # location of the goss executable
AUDIT_BIN_MIN_VER="0.4.4"
AUDIT_FILE="${AUDIT_FILE:-goss.yml}" # the default goss file used by the audit provided by the audit configuration
AUDIT_CONTENT_LOCATION="${AUDIT_CONTENT_LOCATION:-/opt}" # Location of the audit configuration file as available to the OS
# help output
Help()
{
# Display Help
echo "Script to run the goss audit"
echo
echo "Syntax: $0 [-f|-g|-o|-v|-w|-h]"
echo "options:"
echo "-f optional - change the format output (default value = json)"
echo "-g optional - Add a group that the server should be grouped with (default value = ungrouped)"
echo "-o optional - file to output audit data"
echo "-v optional - relative path to thevars file to load (default e.g. $AUDIT_CONTENT_LOCATION/RHEL7-$BENCHMARK/vars/$BENCHMARK.yml)"
echo "-w optional - Sets the system_type to workstation (Default - Server)"
echo "-h Print this Help."
echo
}
# Default vars that can be set
host_system_type=Server
## option statement
while getopts f:g:o:v::wh option; do
case "${option}" in
f ) FORMAT=${OPTARG} ;;
g ) GROUP=${OPTARG} ;;
o ) OUTFILE=${OPTARG} ;;
v ) VARS_PATH=${OPTARG} ;;
w ) host_system_type=Workstation ;;
h ) # display Help
Help
exit;;
? ) # Invalid option
echo "Invalid option: -${OPTARG}."
Help
exit;;
esac
done
#### Pre-Checks
# check access need to run as root or privileges due to some configuration access
if [ "$(/usr/bin/id -u)" -ne 0 ]; then
echo "Script need to run with root privileges"
exit 1
fi
#### Main Script ####
# Discover OS version aligning with audit
# Define os_vendor variable
if [ "$(uname -a | grep -c amzn)" -ge 1 ]; then
os_vendor="AMAZON"
elif [ "$(grep -Ec "rhel|oracle" /etc/os-release)" != 0 ]; then
os_vendor="RHEL"
else
os_vendor="$(hostnamectl | grep Oper | cut -d : -f2 | awk '{print toupper($1)}')"
fi
os_maj_ver="$(grep -w VERSION_ID= /etc/os-release | awk -F\" '{print $2}' | cut -d '.' -f1)"
audit_content_version=$os_vendor$os_maj_ver-$BENCHMARK-Audit
audit_content_dir=$AUDIT_CONTENT_LOCATION/$audit_content_version
audit_vars=vars/${BENCHMARK}.yml
# Set variable for format output
if [ -z "$FORMAT" ]; then
export format="json"
else
export format=$FORMAT
fi
# Set variable for autogroup
if [ -z "$GROUP" ]; then
export host_auto_group="ungrouped"
else
export host_auto_group=$GROUP
fi
# set default variable for varfile_path
if [ -z "$VARS_PATH" ]; then
export varfile_path=$audit_content_dir/$audit_vars
else
# Check -v exists fail if not
if [ -f "$VARS_PATH" ]; then
export varfile_path=$VARS_PATH
else
echo "passed option '-v' $VARS_PATH does not exist"
exit 1
fi
fi
## System variables captured for metadata
host_machine_uuid="$(if [ -f /sys/class/dmi/id/product_uuid ]; then cat /sys/class/dmi/id/product_uuid; else dmidecode -s system-uuid; fi)"
host_epoch="$(date +%s)"
host_os_locale="$(date +%Z)"
host_os_name="$(grep "^NAME=" /etc/os-release | cut -d '"' -f2 | sed 's/ //' | cut -d' ' -f1)"
host_os_version="$(grep "^VERSION_ID=" /etc/os-release | cut -d '"' -f2)"
host_os_hostname="$(hostname)"
## Set variable audit_out
if [ -z "$OUTFILE" ]; then
export audit_out=${AUDIT_CONTENT_LOCATION}/audit_${host_os_hostname}-${BENCHMARK}-${BENCHMARK_OS}_${host_epoch}.$format
else
export audit_out=${OUTFILE}
fi
## Set the AUDIT json string
audit_json_vars='{"benchmark_type":"'"$BENCHMARK"'","benchmark_os":"'"$BENCHMARK_OS"'","benchmark_version":"'"$BENCHMARK_VER"'","machine_uuid":"'"$host_machine_uuid"'","epoch":"'"$host_epoch"'","os_locale":"'"$host_os_locale"'","os_release":"'"$host_os_version"'","os_distribution":"'"$host_os_name"'","os_hostname":"'"$host_os_hostname"'","auto_group":"'"$host_auto_group"'","system_type":"'"$host_system_type"'"}'
## Run pre checks
echo
echo "## Pre-Checks Start"
echo
export FAILURE=0
if [ -s "${AUDIT_BIN}" ]; then
echo "OK - Audit binary $AUDIT_BIN is available"
goss_installed_version="$($AUDIT_BIN -v | awk '{print $NF}' | cut -dv -f2)"
newer_version=$(echo -e "$goss_installed_version\n$AUDIT_BIN_MIN_VER" | sort -V | tail -n 1)
if [ "$goss_installed_version" = "$newer_version" ] || [ "$goss_installed_version" = "$AUDIT_BIN_MIN_VER" ]; then
echo "OK - Goss is installed and version is ok ($goss_installed_version >= $AUDIT_BIN_MIN_VER)"
else
echo "WARNING - Goss installed = ${goss_installed_version}, does not met minimum of ${AUDIT_BIN_MIN_VER}"
export FAILURE=2
fi
else
echo "WARNING - The audit binary is not available at $AUDIT_BIN "
export FAILURE=1
fi
if [ -f "${audit_content_dir}/${AUDIT_FILE}" ]; then
echo "OK - ${audit_content_dir}/${AUDIT_FILE} is available"
else
echo "WARNING - the $audit_content_dir/$AUDIT_FILE is not available"; export FAILURE=3
fi
if [ "${FAILURE}" != 0 ]; then
echo "## Pre-checks failed please see output"
exit 1
else
echo
echo "## Pre-checks Successful"
echo
fi
# format output types
# json, rspecish = grep -A 4 \"summary\": $audit_out
# tap junit no output as no summary
# documentation = tail -2 $audit_out
# defaults
output_summary="tail -2 $audit_out"
format_output="-f $format"
if [ "$format" = json ]; then
format_output="-f json -o pretty"
output_summary='grep -A 4 \"summary\": $audit_out'
elif [ "$format" = junit ] || [ "$format" = tap ]; then
output_summary=""
fi
## Run commands
echo "#############"
echo "Audit Started"
echo "#############"
echo
$AUDIT_BIN -g "$audit_content_dir/$AUDIT_FILE" --vars "$varfile_path" --vars-inline "$audit_json_vars" v $format_output > "$audit_out"
# create screen output
if [ "$(grep -c $BENCHMARK "$audit_out")" != 0 ] || [ "$format" = junit ] || [ "$format" = tap ]; then
eval $output_summary
echo "Completed file can be found at $audit_out"
echo "###############"
echo "Audit Completed"
echo "###############"
else
echo -e "Fail: There were issues when running the audit please investigate $audit_out"
fi