Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
This commit is contained in:
@@ -0,0 +1,420 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
# Script Name: openscap-audit.sh
|
||||
# Description: OpenSCAP / CIS Benchmark security audit script with HTML and
|
||||
# terminal reporting on Ubuntu/Debian and RHEL/Rocky/Alma/Fedora
|
||||
#
|
||||
# Author: Phil Connor
|
||||
# Contact: contact@mylinux.work
|
||||
# Website: https://mylinux.work
|
||||
# License: MIT
|
||||
# Version: 1.0
|
||||
#
|
||||
# Usage:
|
||||
# sudo ./openscap-audit.sh
|
||||
# sudo ./openscap-audit.sh --profile cis_server_l1
|
||||
# sudo ./openscap-audit.sh --report /tmp/audit-report.html
|
||||
# sudo ./openscap-audit.sh --dry-run
|
||||
#
|
||||
################################################################################
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ============================================================================
|
||||
# DEFAULTS
|
||||
# ============================================================================
|
||||
|
||||
PROFILE=""
|
||||
REPORT_DIR="/var/lib/openscap/reports"
|
||||
REPORT_FILE=""
|
||||
RESULTS_FILE=""
|
||||
TAILORING_FILE=""
|
||||
REMEDIATE=false
|
||||
DRY_RUN=false
|
||||
LIST_PROFILES=false
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
# ============================================================================
|
||||
# HELPER FUNCTIONS
|
||||
# ============================================================================
|
||||
|
||||
log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
||||
log_step() { echo -e "${CYAN}[STEP]${NC} $*"; }
|
||||
|
||||
show_usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [OPTIONS]
|
||||
|
||||
Run an OpenSCAP security audit against CIS or DISA STIG benchmarks.
|
||||
|
||||
OPTIONS:
|
||||
--profile PROFILE SCAP profile to evaluate (auto-detected if omitted)
|
||||
--list-profiles List available profiles for this system
|
||||
--report PATH HTML report output path (default: auto-generated in $REPORT_DIR)
|
||||
--results PATH XCCDF results XML output path
|
||||
--tailoring PATH XCCDF tailoring file for custom profile adjustments
|
||||
--remediate Apply automatic remediation (USE WITH CAUTION)
|
||||
--dry-run Show what would be done without executing
|
||||
-h, --help Show this help message
|
||||
|
||||
PROFILES (common):
|
||||
cis_server_l1 CIS Level 1 - Server
|
||||
cis_server_l2 CIS Level 2 - Server
|
||||
cis_workstation_l1 CIS Level 1 - Workstation
|
||||
cis_workstation_l2 CIS Level 2 - Workstation
|
||||
stig DISA STIG
|
||||
standard Standard System Security Profile
|
||||
pci-dss PCI-DSS v3.2.1
|
||||
|
||||
EXAMPLES:
|
||||
$0 # Auto-detect profile and run
|
||||
$0 --profile cis_server_l1 # CIS Level 1 Server
|
||||
$0 --profile stig --report /tmp/stig.html # STIG with custom report path
|
||||
$0 --list-profiles # Show available profiles
|
||||
$0 --remediate --profile cis_server_l1 # Auto-fix (careful!)
|
||||
$0 --dry-run # Preview
|
||||
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help) show_usage ;;
|
||||
--profile) PROFILE="$2"; shift 2 ;;
|
||||
--list-profiles) LIST_PROFILES=true; shift ;;
|
||||
--report) REPORT_FILE="$2"; shift 2 ;;
|
||||
--results) RESULTS_FILE="$2"; shift 2 ;;
|
||||
--tailoring) TAILORING_FILE="$2"; shift 2 ;;
|
||||
--remediate) REMEDIATE=true; shift ;;
|
||||
--dry-run) DRY_RUN=true; shift ;;
|
||||
*) log_error "Unknown option: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
check_root() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
log_error "This script must be run as root (sudo)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
detect_os() {
|
||||
if [[ -f /etc/os-release ]]; then
|
||||
. /etc/os-release
|
||||
OS_ID="$ID"
|
||||
OS_VERSION="${VERSION_ID%%.*}"
|
||||
OS_FAMILY=""
|
||||
case "$OS_ID" in
|
||||
ubuntu|debian) OS_FAMILY="debian" ;;
|
||||
rhel|centos|rocky|almalinux|fedora) OS_FAMILY="rhel" ;;
|
||||
*) log_error "Unsupported OS: $OS_ID"; exit 1 ;;
|
||||
esac
|
||||
log_info "Detected OS: $PRETTY_NAME"
|
||||
else
|
||||
log_error "Cannot detect OS"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# INSTALLATION
|
||||
# ============================================================================
|
||||
|
||||
install_openscap() {
|
||||
if command -v oscap &>/dev/null; then
|
||||
log_info "OpenSCAP already installed: $(oscap --version | head -1)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_step "Installing OpenSCAP..."
|
||||
|
||||
case "$OS_FAMILY" in
|
||||
debian)
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq libopenscap8 openscap-utils ssg-debian ssg-base 2>/dev/null || \
|
||||
apt-get install -y -qq libopenscap8 openscap-utils scap-security-guide 2>/dev/null || \
|
||||
apt-get install -y -qq openscap-scanner openscap-utils scap-security-guide
|
||||
;;
|
||||
rhel)
|
||||
dnf install -y -q openscap-scanner openscap-utils scap-security-guide
|
||||
;;
|
||||
esac
|
||||
|
||||
log_info "OpenSCAP installed: $(oscap --version | head -1)"
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# CONTENT DETECTION
|
||||
# ============================================================================
|
||||
|
||||
find_content() {
|
||||
log_step "Finding SCAP content for $PRETTY_NAME..."
|
||||
|
||||
local content_paths=(
|
||||
"/usr/share/xml/scap/ssg/content"
|
||||
"/usr/share/scap-security-guide"
|
||||
"/usr/share/openscap"
|
||||
)
|
||||
|
||||
SCAP_CONTENT=""
|
||||
|
||||
# Build expected filename patterns based on OS
|
||||
local os_patterns=()
|
||||
case "$OS_ID" in
|
||||
ubuntu) os_patterns=("ssg-ubuntu${OS_VERSION}04-ds.xml" "ssg-ubuntu${OS_VERSION}-ds.xml" "ssg-ubuntu-ds.xml") ;;
|
||||
debian) os_patterns=("ssg-debian${OS_VERSION}-ds.xml" "ssg-debian-ds.xml") ;;
|
||||
rhel) os_patterns=("ssg-rhel${OS_VERSION}-ds.xml" "ssg-rhel-ds.xml") ;;
|
||||
centos) os_patterns=("ssg-centos${OS_VERSION}-ds.xml" "ssg-rhel${OS_VERSION}-ds.xml") ;;
|
||||
rocky) os_patterns=("ssg-rl${OS_VERSION}-ds.xml" "ssg-rhel${OS_VERSION}-ds.xml") ;;
|
||||
almalinux) os_patterns=("ssg-almalinux${OS_VERSION}-ds.xml" "ssg-rhel${OS_VERSION}-ds.xml") ;;
|
||||
fedora) os_patterns=("ssg-fedora-ds.xml") ;;
|
||||
esac
|
||||
|
||||
for dir in "${content_paths[@]}"; do
|
||||
if [[ -d "$dir" ]]; then
|
||||
for pattern in "${os_patterns[@]}"; do
|
||||
if [[ -f "$dir/$pattern" ]]; then
|
||||
SCAP_CONTENT="$dir/$pattern"
|
||||
log_info "Found SCAP content: $SCAP_CONTENT"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
# Fallback: find any matching content
|
||||
SCAP_CONTENT=$(find /usr/share -name "ssg-*-ds.xml" -type f 2>/dev/null | head -1)
|
||||
|
||||
if [[ -z "$SCAP_CONTENT" ]]; then
|
||||
log_error "No SCAP content found for $PRETTY_NAME"
|
||||
log_error "Install scap-security-guide package"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Using SCAP content: $SCAP_CONTENT"
|
||||
}
|
||||
|
||||
list_available_profiles() {
|
||||
log_step "Available profiles for $PRETTY_NAME:"
|
||||
echo ""
|
||||
oscap info --profiles "$SCAP_CONTENT" 2>/dev/null | while IFS=: read -r id title; do
|
||||
printf " %-50s %s\n" "$id" "$title"
|
||||
done
|
||||
echo ""
|
||||
}
|
||||
|
||||
select_profile() {
|
||||
if [[ -n "$PROFILE" ]]; then
|
||||
# Match partial profile names
|
||||
local full_profile
|
||||
full_profile=$(oscap info --profiles "$SCAP_CONTENT" 2>/dev/null | \
|
||||
grep -i "$PROFILE" | head -1 | cut -d: -f1)
|
||||
|
||||
if [[ -n "$full_profile" ]]; then
|
||||
PROFILE="$full_profile"
|
||||
log_info "Selected profile: $PROFILE"
|
||||
else
|
||||
log_error "Profile '$PROFILE' not found"
|
||||
log_info "Available profiles:"
|
||||
list_available_profiles
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Auto-select: prefer CIS Level 1 Server, then STIG, then standard
|
||||
for pattern in "cis.*server.*l1\|cis_server_l1" "stig\b" "standard"; do
|
||||
PROFILE=$(oscap info --profiles "$SCAP_CONTENT" 2>/dev/null | \
|
||||
grep -i "$pattern" | head -1 | cut -d: -f1) || true
|
||||
if [[ -n "$PROFILE" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z "$PROFILE" ]]; then
|
||||
# Use first available profile
|
||||
PROFILE=$(oscap info --profiles "$SCAP_CONTENT" 2>/dev/null | head -1 | cut -d: -f1)
|
||||
fi
|
||||
|
||||
log_info "Auto-selected profile: $PROFILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# AUDIT EXECUTION
|
||||
# ============================================================================
|
||||
|
||||
run_audit() {
|
||||
local timestamp
|
||||
timestamp=$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
mkdir -p "$REPORT_DIR"
|
||||
|
||||
if [[ -z "$REPORT_FILE" ]]; then
|
||||
REPORT_FILE="$REPORT_DIR/openscap-report-${timestamp}.html"
|
||||
fi
|
||||
|
||||
if [[ -z "$RESULTS_FILE" ]]; then
|
||||
RESULTS_FILE="$REPORT_DIR/openscap-results-${timestamp}.xml"
|
||||
fi
|
||||
|
||||
log_step "Running OpenSCAP audit..."
|
||||
log_info "Profile: $PROFILE"
|
||||
log_info "Content: $SCAP_CONTENT"
|
||||
log_info "Report: $REPORT_FILE"
|
||||
log_info "Results: $RESULTS_FILE"
|
||||
echo ""
|
||||
|
||||
local oscap_cmd=(
|
||||
oscap xccdf eval
|
||||
--profile "$PROFILE"
|
||||
--report "$REPORT_FILE"
|
||||
--results "$RESULTS_FILE"
|
||||
)
|
||||
|
||||
if [[ -n "$TAILORING_FILE" ]] && [[ -f "$TAILORING_FILE" ]]; then
|
||||
oscap_cmd+=(--tailoring-file "$TAILORING_FILE")
|
||||
fi
|
||||
|
||||
if [[ "$REMEDIATE" == true ]]; then
|
||||
oscap_cmd+=(--remediate)
|
||||
log_warn "REMEDIATION ENABLED — changes will be applied!"
|
||||
fi
|
||||
|
||||
oscap_cmd+=("$SCAP_CONTENT")
|
||||
|
||||
# oscap returns exit code 2 for "some checks failed" — that's normal
|
||||
local exit_code=0
|
||||
"${oscap_cmd[@]}" 2>&1 || exit_code=$?
|
||||
|
||||
if [[ $exit_code -eq 0 ]]; then
|
||||
log_info "All checks passed"
|
||||
elif [[ $exit_code -eq 2 ]]; then
|
||||
log_warn "Some checks failed (this is normal for a first audit)"
|
||||
else
|
||||
log_error "OpenSCAP encountered an error (exit code: $exit_code)"
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# RESULTS SUMMARY
|
||||
# ============================================================================
|
||||
|
||||
show_summary() {
|
||||
log_step "Audit Summary"
|
||||
echo ""
|
||||
|
||||
if [[ -f "$RESULTS_FILE" ]]; then
|
||||
local pass fail error notapplicable notchecked total score
|
||||
pass=$(grep -c 'result="pass"' "$RESULTS_FILE" 2>/dev/null) || pass=0
|
||||
fail=$(grep -c 'result="fail"' "$RESULTS_FILE" 2>/dev/null) || fail=0
|
||||
error=$(grep -c 'result="error"' "$RESULTS_FILE" 2>/dev/null) || error=0
|
||||
notapplicable=$(grep -c 'result="notapplicable"' "$RESULTS_FILE" 2>/dev/null) || notapplicable=0
|
||||
notchecked=$(grep -c 'result="notchecked"' "$RESULTS_FILE" 2>/dev/null) || notchecked=0
|
||||
total=$((pass + fail))
|
||||
|
||||
if [[ $total -gt 0 ]]; then
|
||||
score=$(echo "scale=1; $pass * 100 / $total" | bc)
|
||||
else
|
||||
score=0
|
||||
fi
|
||||
|
||||
echo -e " ${GREEN}Pass:${NC} $pass"
|
||||
echo -e " ${RED}Fail:${NC} $fail"
|
||||
echo -e " ${YELLOW}Error:${NC} $error"
|
||||
echo -e " Not Applicable: $notapplicable"
|
||||
echo -e " Not Checked: $notchecked"
|
||||
echo ""
|
||||
echo -e " ${CYAN}Compliance Score:${NC} ${score}%"
|
||||
echo ""
|
||||
|
||||
# Show top failures
|
||||
if [[ $fail -gt 0 ]]; then
|
||||
log_info "Top failed rules (first 10):"
|
||||
grep -B2 'result="fail"' "$RESULTS_FILE" 2>/dev/null | \
|
||||
grep 'idref=' | sed 's/.*idref="\([^"]*\)".*/ - \1/' | head -10
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
log_info "HTML report: $REPORT_FILE"
|
||||
log_info "XML results: $RESULTS_FILE"
|
||||
|
||||
if [[ $fail -gt 0 ]]; then
|
||||
echo ""
|
||||
log_info "To auto-remediate failed checks (USE WITH CAUTION):"
|
||||
echo " $0 --profile '$PROFILE' --remediate"
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# DRY RUN
|
||||
# ============================================================================
|
||||
|
||||
dry_run() {
|
||||
echo ""
|
||||
log_info "===== DRY RUN — No changes will be made ====="
|
||||
echo ""
|
||||
log_info "OS: $PRETTY_NAME"
|
||||
log_info "Content: $SCAP_CONTENT"
|
||||
log_info "Profile: $PROFILE"
|
||||
log_info "Report dir: $REPORT_DIR"
|
||||
log_info "Remediate: $REMEDIATE"
|
||||
echo ""
|
||||
log_info "Actions that would be performed:"
|
||||
echo " 1. Install OpenSCAP (if not present)"
|
||||
echo " 2. Find SCAP content for $OS_ID $OS_VERSION"
|
||||
echo " 3. Evaluate profile: $PROFILE"
|
||||
echo " 4. Generate HTML report in $REPORT_DIR/"
|
||||
echo " 5. Generate XCCDF results XML"
|
||||
if [[ "$REMEDIATE" == true ]]; then
|
||||
echo " 6. APPLY REMEDIATION for failed checks"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# MAIN
|
||||
# ============================================================================
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
check_root
|
||||
detect_os
|
||||
install_openscap
|
||||
find_content
|
||||
|
||||
if [[ "$LIST_PROFILES" == true ]]; then
|
||||
list_available_profiles
|
||||
exit 0
|
||||
fi
|
||||
|
||||
select_profile
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
dry_run
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_info "===== OpenSCAP Security Audit ====="
|
||||
echo ""
|
||||
|
||||
run_audit
|
||||
show_summary
|
||||
|
||||
echo ""
|
||||
log_info "===== Audit Complete ====="
|
||||
echo ""
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user