#!/usr/bin/env bash
#
# onx-modsec-enable — ModSecurity engine ON/DetectionOnly + full settings.
#
# v3.41 DRIVER-AWARE:
#   Apache → /etc/httpd/modsecurity.d/onox-engine.conf (mevcut davranış korunur)
#   v3 (nginx/ols/caddy) → neutral layer 00-engine.conf (driver main config Include eder)
#
# Audit log YOLU sürücüye özgü: Apache'de bu dosyada set edilir; v3'te driver
# main config'te (onx-modsec-install-driver) set edilir → burada SET ETME (duplicate).
#
# Input (controller updateSettings payload — hepsi opsiyonel):
#   { mode, ruleset, paranoia_level, audit_log_enabled, audit_log_parts,
#     request_body_access, response_body_access, request_body_limit,
#     request_body_nofiles_limit, anomaly_threshold_inbound, anomaly_threshold_outbound,
#     auto_exclude_wordpress, auto_exclude_drupal, auto_exclude_joomla }
# Output: {ok, enabled, driver, engine, ruleset, paranoia_level, reloaded, conf_file}

set -euo pipefail

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=_lib/common.sh
source "${SCRIPT_DIR}/_lib/common.sh"

require_root
onx_json_input

mode=$(onx_json_field        "mode" "on")            # on|detection_only|off
ruleset=$(onx_json_field     "ruleset" "OWASP-CRS-3.3")
paranoia=$(onx_json_field    "paranoia_level" "2")
audit_enabled=$(onx_json_get_bool "$INPUT" "audit_log_enabled" "true")
audit_parts=$(onx_json_field "audit_log_parts" "ABIJDEFHZ")
req_body=$(onx_json_get_bool  "$INPUT" "request_body_access" "true")
resp_body=$(onx_json_get_bool "$INPUT" "response_body_access" "true")
req_limit=$(onx_json_field   "request_body_limit" "13107200")
req_nofiles=$(onx_json_field "request_body_nofiles_limit" "131072")
anomaly_in=$(onx_json_field  "anomaly_threshold_inbound" "5")
anomaly_out=$(onx_json_field "anomaly_threshold_outbound" "4")
excl_wp=$(onx_json_get_bool     "$INPUT" "auto_exclude_wordpress" "false")
excl_drupal=$(onx_json_get_bool "$INPUT" "auto_exclude_drupal" "false")
excl_joomla=$(onx_json_get_bool "$INPUT" "auto_exclude_joomla" "false")

# ── Validation ───────────────────────────────────────────────────────────────
[[ "$paranoia"    =~ ^[1-4]$    ]] || onx_die 1 "paranoia_level must be 1-4"
[[ "$audit_parts" =~ ^[A-Z]+$   ]] || audit_parts="ABIJDEFHZ"
[[ "$req_limit"   =~ ^[0-9]+$   ]] || req_limit=13107200
[[ "$req_nofiles" =~ ^[0-9]+$   ]] || req_nofiles=131072
[[ "$anomaly_in"  =~ ^[0-9]+$   ]] || anomaly_in=5
[[ "$anomaly_out" =~ ^[0-9]+$   ]] || anomaly_out=4
case "$ruleset" in
    OWASP-CRS-3.3|OWASP-CRS-4.0|Comodo-CWAF|Custom) ;;
    *) ruleset="OWASP-CRS-3.3" ;;
esac

# ── Engine value from mode ───────────────────────────────────────────────────
case "$mode" in
    on)             engine="On" ;;
    detection_only) engine="DetectionOnly" ;;
    off)            engine="Off" ;;
    *)              engine="On" ;;
esac
enabled_bool=true
[[ "$engine" == "Off" ]] && enabled_bool=false

audit_engine="RelevantOnly"
[[ "$audit_enabled" != "true" ]] && audit_engine="Off"
rba="On";  [[ "$req_body"  != "true" ]] && rba="Off"
rsba="On"; [[ "$resp_body" != "true" ]] && rsba="Off"

# ── Resolve active driver + target engine file ───────────────────────────────
DRIVER=$(onx_ws_active_driver)
audit_log_line=""
if [[ "$DRIVER" == "apache" ]]; then
    ENGINE_FILE="/etc/httpd/modsecurity.d/onox-engine.conf"
    # Apache'de audit path bu dosyada (mevcut davranış)
    audit_log_line="SecAuditLog /var/log/httpd/modsec_audit.log"
elif [[ "$DRIVER" == "unknown" ]]; then
    onx_die 2 "Aktif web sunucusu tespit edilemedi (apache/ols/nginx/caddy hiçbiri active değil)"
else
    ENGINE_FILE="${ONX_MODSEC_NEUTRAL_DIR}/${ONX_MODSEC_NEUTRAL_SUBDIR}/00-engine.conf"
    # v3'te audit path driver main config'te — burada SET ETME (duplicate önlenir)
    mkdir -p "$(dirname "$ENGINE_FILE")" 2>/dev/null || true
fi

# App-based CRS exclusion setvar'ları (plugin dosyaları varsa devreye girer)
app_excl=""
[[ "$excl_wp"     == "true" ]] && app_excl+=",setvar:tx.crs_exclusions_wordpress=1"
[[ "$excl_drupal" == "true" ]] && app_excl+=",setvar:tx.crs_exclusions_drupal=1"
[[ "$excl_joomla" == "true" ]] && app_excl+=",setvar:tx.crs_exclusions_joomla=1"

# ── Backup (rollback için) ────────────────────────────────────────────────────
backup=""
if [[ -f "$ENGINE_FILE" ]]; then
    backup="${ENGINE_FILE}.onx-bak.$$"
    cp -p "$ENGINE_FILE" "$backup"
fi

# ── Compose (container-free — Apache + libmodsecurity v3 ortak) ──────────────
tmp="$(mktemp -t onx-modsec.XXXXXX)"
{
    echo "# Onoxsoft Panel managed — DO NOT EDIT (UI: Admin > ModSecurity > Settings)"
    echo "# Driver: ${DRIVER} | ruleset: ${ruleset} | generated $(date -u +%Y-%m-%dT%H:%M:%SZ)"
    echo "SecRuleEngine ${engine}"
    echo "SecRequestBodyAccess ${rba}"
    echo "SecResponseBodyAccess ${rsba}"
    echo "SecRequestBodyLimit ${req_limit}"
    echo "SecRequestBodyNoFilesLimit ${req_nofiles}"
    echo "SecRequestBodyLimitAction Reject"
    echo "SecAuditEngine ${audit_engine}"
    echo "SecAuditLogParts ${audit_parts}"
    echo 'SecAuditLogRelevantStatus "^(?:5|4(?!04))"'
    if [[ -n "$audit_log_line" ]]; then echo "$audit_log_line"; fi
    # Paranoia (id 900100 — CRS'in 900000'i ile çakışmaz, crs-setup SONRASI override)
    echo "SecAction \"id:900100,phase:1,nolog,pass,t:none,setvar:tx.paranoia_level=${paranoia},setvar:tx.blocking_paranoia_level=${paranoia},setvar:tx.detection_paranoia_level=${paranoia}\""
    # Anomaly skor eşikleri (id 900110)
    echo "SecAction \"id:900110,phase:1,nolog,pass,t:none,setvar:tx.inbound_anomaly_score_threshold=${anomaly_in},setvar:tx.outbound_anomaly_score_threshold=${anomaly_out}\""
    # App-based exclusions (id 900120) — yalnızca en az biri açıksa
    if [[ -n "$app_excl" ]]; then
        echo "SecAction \"id:900120,phase:1,nolog,pass,t:none${app_excl}\""
    fi
} > "$tmp"
chmod 0644 "$tmp"
mv -f "$tmp" "$ENGINE_FILE"

# ── configtest + reload (helper configtest yapar; başarısızsa reload etmez) ──
reloaded=$(onx_ws_modsec_reload "$DRIVER")
if [[ "$reloaded" != "true" ]]; then
    # Rollback — eski dosyayı geri yükle, tekrar reload dene
    if [[ -n "$backup" ]]; then
        mv -f "$backup" "$ENGINE_FILE" 2>/dev/null || true
    else
        rm -f "$ENGINE_FILE" 2>/dev/null || true
    fi
    onx_ws_modsec_reload "$DRIVER" >/dev/null 2>&1 || true
    onx_log "modsec-enable: driver=${DRIVER} reload/configtest FAILED — rolled back"
    jq -nc --arg driver "$DRIVER" --arg engine "$engine" \
        '{ok:false,error:"reload/configtest failed — rolled back",driver:$driver,engine:$engine}' >&2
    exit 4
fi
[[ -n "$backup" ]] && rm -f "$backup" 2>/dev/null || true

logger -t "onox-modsec" "Enabled driver=${DRIVER} engine=${engine} ruleset=${ruleset} paranoia=${paranoia} reloaded=${reloaded}"

jq -nc \
    --arg driver "$DRIVER" \
    --arg engine "$engine" \
    --arg ruleset "$ruleset" \
    --argjson paranoia "$paranoia" \
    --argjson enabled "$enabled_bool" \
    --arg file "$ENGINE_FILE" \
    '{ok:true, enabled:$enabled, driver:$driver, engine:$engine, mode:$engine,
      ruleset:$ruleset, paranoia_level:$paranoia, reloaded:true, conf_file:$file}'
