#!/usr/bin/env bash
set -Eeuo pipefail

: "${EDGESHIELD_GENERATED_DIR:=/var/lib/edgeshield/generated}"
: "${EDGESHIELD_WAF_CONF:=/etc/edgeshield/waf/modsecurity.conf}"
: "${EDGESHIELD_WAF_PORT:=8082}"
: "${EDGESHIELD_REALIP_FROM:=127.0.0.1}"
: "${EDGESHIELD_REALIP_FROM_EXTRA:=::1}"
: "${EDGESHIELD_REALIP_HEADER:=X-Forwarded-For}"
: "${EDGESHIELD_NGINX_RELOAD:=1}"

mkdir -p "${EDGESHIELD_GENERATED_DIR}" /etc/edgeshield/waf /var/log/nginx /var/log/modsecurity /var/lib/edgeshield/generated/waf
# Do not truncate logs on repeated helper runs; keep history for the UI.
touch /var/log/nginx/edgeshield.access.jsonl \
      /var/log/nginx/edgeshield.error.log \
      /var/log/modsecurity/audit.log

# Ensure blocking mode is truly disruptive for CRS anomaly evaluation.
# In DetectionOnly this is harmless: ModSecurity logs detections and does not block.
if [ ! -s /var/lib/edgeshield/generated/waf/50-niceos-crs-anomaly-enforcement.after.conf ]; then
  cat > /var/lib/edgeshield/generated/waf/50-niceos-crs-anomaly-enforcement.after.conf <<'EOF_ENFORCE'
# NiceOS EdgeShield CRS anomaly enforcement overlay.
SecRuleUpdateActionById 949110 "deny,status:403,log,auditlog"
SecRuleUpdateActionById 959100 "deny,status:403,log,auditlog"
EOF_ENFORCE
fi

if [ ! -f "${EDGESHIELD_WAF_CONF}" ]; then
  cat > "${EDGESHIELD_WAF_CONF}" <<'WAF'
# NiceOS EdgeShield ModSecurity runtime config.
SecRuleEngine DetectionOnly
SecRequestBodyAccess On
SecResponseBodyAccess Off
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyLimitAction Reject
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogType Serial
SecAuditLogFormat JSON
SecAuditLog /var/log/modsecurity/audit.log
SecTmpDir /tmp/
SecDataDir /tmp/
SecUnicodeMapFile /etc/modsecurity/unicode.mapping 20127
IncludeOptional /var/lib/edgeshield/generated/waf/*.before.conf
Include /etc/modsecurity.d/owasp-crs/rules.conf
IncludeOptional /var/lib/edgeshield/generated/waf/*.after.conf
WAF
fi

if ! grep -q '/etc/modsecurity.d/owasp-crs/rules.conf' "${EDGESHIELD_WAF_CONF}"; then
  echo "ERROR: ${EDGESHIELD_WAF_CONF} does not include /etc/modsecurity.d/owasp-crs/rules.conf" >&2
  echo "Install niceos-edgeshield-config-waf >= 0.1.1 or update the WAF config first." >&2
  exit 65
fi

cat > "${EDGESHIELD_GENERATED_DIR}/60-edgeshield-waf-observability.conf" <<EOF_NGINX
server {
    listen ${EDGESHIELD_WAF_PORT};
    server_name edgeshield_waf_observability;

    root /usr/share/nginx/html;
    index index.html;

    set_real_ip_from ${EDGESHIELD_REALIP_FROM};
    set_real_ip_from ${EDGESHIELD_REALIP_FROM_EXTRA};
    real_ip_header ${EDGESHIELD_REALIP_HEADER};
    real_ip_recursive on;

    access_log /var/log/nginx/edgeshield.access.jsonl edgeshield_access_v3 buffer=64k flush=1s;
    error_log  /var/log/nginx/edgeshield.error.log warn;

    modsecurity on;
    modsecurity_rules_file ${EDGESHIELD_WAF_CONF};

    edgeshield_telemetry_server_zone edgeshield_waf_observability;

    location = /healthz {
        access_log off;
        add_header Content-Type text/plain;
        return 200 "ok\n";
    }

    location / {
        edgeshield_telemetry_location_zone edgeshield_waf_root;
        try_files \$uri /index.html =404;
    }
}
EOF_NGINX

nginx -t
if [ "${EDGESHIELD_NGINX_RELOAD}" = "1" ]; then
  nginx -s reload || nginx
fi

cat <<EOF_OK
OK: EdgeShield WAF observability enabled
port=${EDGESHIELD_WAF_PORT}
waf=${EDGESHIELD_WAF_CONF}
realip_from=${EDGESHIELD_REALIP_FROM}
realip_from_extra=${EDGESHIELD_REALIP_FROM_EXTRA}
realip_header=${EDGESHIELD_REALIP_HEADER}
enforcement_overlay=/var/lib/edgeshield/generated/waf/50-niceos-crs-anomaly-enforcement.after.conf
access_log=/var/log/nginx/edgeshield.access.jsonl
audit_log=/var/log/modsecurity/audit.log
smoke:
  curl -i 'http://127.0.0.1:${EDGESHIELD_WAF_PORT}/?q=%27%20or%201=1--' -H 'User-Agent: sqlmap/1.7' -H 'X-Forwarded-For: 8.8.8.8'
EOF_OK
