Files
linux-scripts/fapolicyd-log-analyzer.sh
chiefgeek a1a17e81a1 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.
2026-05-25 03:31:08 +02:00

388 lines
14 KiB
Bash

#!/bin/bash
#############################################################
#### fapolicyd Log Analyzer Script ####
#### Parses denial logs and suggests fix commands ####
#### ####
#### Author: Phil Connor ####
#### Contact: contact@mylinux.work ####
#### License: MIT ####
#### Version 1.00 ####
#### ####
#### To use this script chmod it to 755 ####
#### or simply type bash <filename.sh> ####
#############################################################
# ── Colors ────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# ── Defaults ──────────────────────────────────────────────
MODE="recent"
OUTPUT_FILE=""
QUIET=0
TOTAL_DENIALS=0
UNIQUE_FILES=0
SUGGESTED_FIXES=0
# ── Functions ─────────────────────────────────────────────
usage() {
echo -e "${BOLD}fapolicyd Log Analyzer${NC}"
echo ""
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " --help Show this help message"
echo " --recent Analyze denials from the last hour only (default)"
echo " --all Analyze all denials in the log"
echo " --output FILE Save suggested fixes to FILE"
echo " --quiet Show suggestions only, suppress raw denial lines"
echo ""
echo "Examples:"
echo " sudo bash $0 --recent"
echo " sudo bash $0 --all --output fixes.txt"
echo " sudo bash $0 --quiet --output /tmp/fixes.txt"
exit 0
}
check_root() {
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}Error: This script must be run as root.${NC}"
echo "Please run with: sudo bash $0"
exit 1
fi
}
check_fapolicyd() {
if ! command -v fapolicyd-cli &>/dev/null; then
echo -e "${RED}Error: fapolicyd does not appear to be installed.${NC}"
echo -e "${YELLOW}Install with: dnf install fapolicyd${NC}"
exit 1
fi
if ! systemctl is-active --quiet fapolicyd 2>/dev/null; then
echo -e "${YELLOW}Warning: fapolicyd service is not currently running.${NC}"
echo -e "${CYAN}Continuing to analyze existing log entries...${NC}"
echo ""
fi
}
output_line() {
local line="$1"
echo -e "$line"
if [[ -n "$OUTPUT_FILE" ]]; then
echo -e "$line" | sed 's/\x1b\[[0-9;]*m//g' >> "$OUTPUT_FILE"
fi
}
# ── fapolicyd Analysis ───────────────────────────────────
parse_fapolicyd_denial() {
local line="$1"
local dec perm fname exe trust pid
dec=$(echo "$line" | grep -oP 'dec=\K[^ ]+')
perm=$(echo "$line" | grep -oP 'perm=\K[^ ]+')
fname=$(echo "$line" | grep -oP 'fname=\K[^ ]+')
exe=$(echo "$line" | grep -oP 'exe=\K[^ ]+')
trust=$(echo "$line" | grep -oP 'trust=\K[^ ]+')
pid=$(echo "$line" | grep -oP 'pid=\K[^ ]+')
if [[ $QUIET -eq 0 ]]; then
output_line "${RED}DENIAL:${NC} $line"
fi
[[ -n "$dec" ]] && output_line "${CYAN} Decision:${NC} $dec"
[[ -n "$perm" ]] && output_line "${CYAN} Permission:${NC} $perm"
[[ -n "$fname" ]] && output_line "${CYAN} File:${NC} $fname"
[[ -n "$exe" ]] && output_line "${CYAN} Executable:${NC} $exe"
[[ -n "$trust" ]] && output_line "${CYAN} Trust status:${NC} $trust"
[[ -n "$pid" ]] && output_line "${CYAN} PID:${NC} $pid"
suggest_fapolicyd_fix "$fname" "$exe" "$perm" "$trust"
output_line ""
}
suggest_fapolicyd_fix() {
local fname="$1" exe="$2" perm="$3" trust="$4"
((SUGGESTED_FIXES++))
if [[ -n "$fname" ]]; then
# Check current trust status
output_line "${GREEN} Suggested fixes:${NC}"
# Trust the file
output_line "${GREEN} 1. Add file to trust database:${NC}"
output_line "${GREEN} fapolicyd-cli --file add ${fname}${NC}"
output_line "${GREEN} fapolicyd-cli --update${NC}"
# Check trust
output_line "${GREEN} 2. Verify trust status:${NC}"
output_line "${GREEN} fapolicyd-cli --check-path ${fname}${NC}"
# If the file is a script or binary from a known package
if command -v rpm &>/dev/null; then
local pkg
pkg=$(rpm -qf "$fname" 2>/dev/null)
if [[ $? -eq 0 && -n "$pkg" ]]; then
output_line "${CYAN} Note: File belongs to package: ${pkg}${NC}"
output_line "${YELLOW} If the file was modified after install, consider:${NC}"
output_line "${GREEN} rpm --restore ${pkg}${NC}"
output_line "${GREEN} fapolicyd-cli --update${NC}"
fi
fi
# If it looks like a shared library
if [[ "$fname" == *.so* ]]; then
output_line "${YELLOW} Library denial — also check:${NC}"
output_line "${GREEN} ldconfig${NC}"
output_line "${GREEN} fapolicyd-cli --update${NC}"
fi
fi
# Suggest rule-based approach
if [[ -n "$exe" && -n "$perm" ]]; then
output_line "${GREEN} 3. Or add a custom rule in /etc/fapolicyd/rules.d/:${NC}"
output_line "${GREEN} allow ${perm} exe=${exe} : all${NC}"
fi
}
categorize_fapolicyd_denial() {
local line="$1"
local perm fname
perm=$(echo "$line" | grep -oP 'perm=\K[^ ]+')
fname=$(echo "$line" | grep -oP 'fname=\K[^ ]+')
case "$perm" in
execute)
if [[ "$fname" == *.so* ]]; then
echo "library"
else
echo "execute"
fi
;;
open)
echo "open"
;;
*)
echo "other"
;;
esac
}
analyze_fapolicyd() {
output_line "${BOLD}═══════════════════════════════════════════════════${NC}"
output_line "${BOLD} fapolicyd Log Analysis${NC}"
output_line "${BOLD}═══════════════════════════════════════════════════${NC}"
output_line ""
# Show daemon status
local daemon_status
daemon_status=$(systemctl is-active fapolicyd 2>/dev/null)
output_line "${CYAN}fapolicyd status:${NC} $daemon_status"
# Show integrity setting
if [[ -f /etc/fapolicyd/fapolicyd.conf ]]; then
local integrity
integrity=$(grep -oP '^\s*integrity\s*=\s*\K.*' /etc/fapolicyd/fapolicyd.conf 2>/dev/null)
[[ -n "$integrity" ]] && output_line "${CYAN}Integrity mode:${NC} $integrity"
fi
# Show trust database stats
if command -v fapolicyd-cli &>/dev/null; then
local trust_count
trust_count=$(fapolicyd-cli --dump-db 2>/dev/null | wc -l)
[[ -n "$trust_count" ]] && output_line "${CYAN}Trusted files:${NC} $trust_count"
fi
output_line ""
# Gather denials from audit log
local denials=""
if [[ ! -f /var/log/audit/audit.log ]]; then
output_line "${RED}Error: Cannot find /var/log/audit/audit.log${NC}"
output_line "${YELLOW}Ensure auditd is running: systemctl start auditd${NC}"
return
fi
if [[ "$MODE" == "recent" ]]; then
if command -v ausearch &>/dev/null; then
denials=$(ausearch -m FANOTIFY -ts recent 2>/dev/null | grep "type=FANOTIFY")
fi
# Fallback to manual log parsing
if [[ -z "$denials" ]]; then
local one_hour_ago
one_hour_ago=$(date -d '1 hour ago' '+%s' 2>/dev/null)
if [[ -n "$one_hour_ago" ]]; then
denials=$(awk -v cutoff="$one_hour_ago" '
/type=FANOTIFY/ && /dec=deny/ {
match($0, /msg=audit\(([0-9]+)\./, arr)
if (arr[1] >= cutoff) print
}
' /var/log/audit/audit.log)
fi
fi
else
denials=$(grep "type=FANOTIFY" /var/log/audit/audit.log | grep "dec=deny")
fi
if [[ -z "$denials" ]]; then
output_line "${GREEN}No fapolicyd denials found.${NC}"
output_line ""
return
fi
# Group denials by category
declare -A categories
local denial_count=0
local -A seen_files
while IFS= read -r line; do
[[ -z "$line" ]] && continue
((denial_count++))
local category
category=$(categorize_fapolicyd_denial "$line")
categories["$category"]+="$line"$'\n'
local f
f=$(echo "$line" | grep -oP 'fname=\K[^ ]+')
[[ -n "$f" ]] && seen_files["$f"]=1
done <<< "$denials"
TOTAL_DENIALS=$denial_count
UNIQUE_FILES=${#seen_files[@]}
# Display grouped results
for category in "execute" "library" "open" "other"; do
if [[ -n "${categories[$category]}" ]]; then
local label
case "$category" in
execute) label="Execution Denials" ;;
library) label="Library Load Denials" ;;
open) label="File Open Denials" ;;
other) label="Other Denials" ;;
esac
output_line "${BOLD}── ${label} ──────────────────────────────────${NC}"
output_line ""
while IFS= read -r denial_line; do
[[ -z "$denial_line" ]] && continue
parse_fapolicyd_denial "$denial_line"
done <<< "${categories[$category]}"
fi
done
# Show bulk fix suggestions
if [[ ${#seen_files[@]} -gt 0 ]]; then
output_line "${BOLD}── Bulk Fix Commands ────────────────────────────${NC}"
output_line ""
output_line "${YELLOW}To trust all denied files at once:${NC}"
for f in "${!seen_files[@]}"; do
output_line "${GREEN} fapolicyd-cli --file add ${f}${NC}"
done
output_line "${GREEN} fapolicyd-cli --update${NC}"
output_line ""
fi
# Rule file reference
output_line "${BOLD}── Rule File Reference ──────────────────────────${NC}"
output_line ""
output_line "${CYAN}Rules are loaded from:${NC}"
if [[ -d /etc/fapolicyd/rules.d ]]; then
output_line " /etc/fapolicyd/rules.d/ (drop-in directory)"
local rule_files
rule_files=$(ls /etc/fapolicyd/rules.d/ 2>/dev/null)
if [[ -n "$rule_files" ]]; then
output_line "${CYAN} Current rule files:${NC}"
while IFS= read -r rf; do
output_line " $rf"
done <<< "$rule_files"
fi
fi
if [[ -f /etc/fapolicyd/fapolicyd.rules ]]; then
output_line " /etc/fapolicyd/fapolicyd.rules (compiled rules)"
fi
output_line ""
output_line "${YELLOW}After making changes, restart the daemon:${NC}"
output_line "${GREEN} systemctl restart fapolicyd${NC}"
output_line ""
}
# ── Summary ───────────────────────────────────────────────
print_summary() {
output_line "${BOLD}═══════════════════════════════════════════════════${NC}"
output_line "${BOLD} Summary${NC}"
output_line "${BOLD}═══════════════════════════════════════════════════${NC}"
output_line ""
output_line " Total denials found: ${BOLD}${TOTAL_DENIALS}${NC}"
output_line " Unique files denied: ${BOLD}${UNIQUE_FILES}${NC}"
output_line " Suggested fixes: ${BOLD}${SUGGESTED_FIXES}${NC}"
output_line ""
if [[ -n "$OUTPUT_FILE" ]]; then
output_line "${GREEN}Suggestions saved to: ${OUTPUT_FILE}${NC}"
output_line ""
fi
}
# ── Parse Arguments ───────────────────────────────────────
while [[ $# -gt 0 ]]; do
case "$1" in
--help|-h)
usage
;;
--recent)
MODE="recent"
shift
;;
--all)
MODE="all"
shift
;;
--output)
if [[ -z "$2" || "$2" == --* ]]; then
echo -e "${RED}Error: --output requires a filename argument.${NC}"
exit 1
fi
OUTPUT_FILE="$2"
shift 2
;;
--quiet|-q)
QUIET=1
shift
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
echo "Use --help for usage information."
exit 1
;;
esac
done
# ── Main ──────────────────────────────────────────────────
check_root
# Clear output file if specified
if [[ -n "$OUTPUT_FILE" ]]; then
> "$OUTPUT_FILE"
fi
echo -e "${BOLD}fapolicyd Log Analyzer v1.00${NC}"
echo -e "${CYAN}Mode: ${MODE}${NC}"
echo ""
check_fapolicyd
analyze_fapolicyd
print_summary