#!/bin/bash

TARGET=""
IP=$(ip a s enp0s3 | grep "inet\>" | awk '{ print $2 }' | cut -f 1 -d /)

while getopts "t:" opt; do
  case $opt in
    t) TARGET="$OPTARG" ;;
    *) echo "Ungueltige Option" >&2; exit 1 ;;
  esac
done

if [[ -z "$TARGET" ]]; then
  echo "Fehlendes TARGET! Nutzung: $0 -t <TARGET>"
  exit 1
fi

# ============================================================
echo "=== Tabula Rasa ==="
# ============================================================
systemctl stop coraza-spoa 2>/dev/null || true
systemctl disable coraza-spoa 2>/dev/null || true
apt purge -y haproxy golang-go 2>/dev/null || true
rm -fr /etc/haproxy /etc/coraza-spoa /opt/coraza-spoa /var/log/coraza
rm -f  /usr/local/bin/coraza-spoa
rm -f  /etc/systemd/system/coraza-spoa.service
systemctl daemon-reload

# ============================================================
echo "=== Install HAProxy ==="
# ============================================================
apt install -y haproxy

echo "=== SSL Stuff ==="
mkdir -p /etc/haproxy/ssl
cat /etc/ssl/own.crt /etc/ssl/own.key > /etc/haproxy/ssl/revproxy.pem
chmod 600 /etc/haproxy/ssl/revproxy.pem

# ============================================================
echo "=== Install Coraza SPOA ==="
# ============================================================
apt install -y golang-go git
git clone https://github.com/corazawaf/coraza-spoa.git /opt/coraza-spoa
cd /opt/coraza-spoa
go build -o /usr/local/bin/coraza-spoa .
cd /

echo "=== OWASP Core Rule Set ==="
mkdir -p /etc/coraza-spoa/crs
git clone https://github.com/coreruleset/coreruleset.git /etc/coraza-spoa/crs
cp /etc/coraza-spoa/crs/crs-setup.conf.example /etc/coraza-spoa/crs/crs-setup.conf
mkdir -p /var/log/coraza

echo "=== Coraza YAML Konfiguration ==="
cat <<'YAML' > /etc/coraza-spoa/coraza-spoa.yaml
bind_address: 127.0.0.1:9000
log_level: info
log_file: /var/log/coraza/coraza-spoa.log

applications:
  - name: sample_app
    directives: |
      Include /etc/coraza-spoa/crs/crs-setup.conf
      Include /etc/coraza-spoa/crs/rules/*.conf
      SecRuleEngine On
      SecRequestBodyAccess On
      SecResponseBodyAccess On
      SecAuditLog /var/log/coraza/audit.log
      SecAuditLogType Serial
      SecAuditEngine RelevantOnly
YAML

echo "=== SPOE Config fuer HAProxy ==="
# WICHTIG fuer HAProxy 3.x:
# - Section-Header [coraza] muss mit dem engine-Namen in haproxy.cfg uebereinstimmen
# - spoe-agent Name ist beliebig, aber muss im [scope] stehen
# - Leerzeile am Dateiende zwingend (sonst: "Missing LF on last line")
cat <<'SPOE' > /etc/haproxy/coraza.cfg
[coraza]
spoe-agent coraza-agent
    messages        coraza-req
    option          var-prefix      coraza
    option          set-on-error    error
    timeout         hello           2s
    timeout         idle            2m
    timeout         processing      500ms
    use-backend     coraza-spoa

spoe-message coraza-req
    args app=str(sample_app) id=unique-id src-ip=src src-port=src_port dst-ip=dst dst-port=dst_port method=method path=path query=query version=req.ver headers=req.hdrs body=req.body
    event on-frontend-http-request

SPOE

echo "=== Coraza Systemd Service ==="
cat <<'SERVICE' > /etc/systemd/system/coraza-spoa.service
[Unit]
Description=Coraza SPOA for HAProxy
After=network.target

[Service]
ExecStart=/usr/local/bin/coraza-spoa -config /etc/coraza-spoa/coraza-spoa.yaml
Restart=on-failure
User=haproxy

[Install]
WantedBy=multi-user.target
SERVICE

systemctl daemon-reload
systemctl enable --now coraza-spoa

# ============================================================
echo "=== HAProxy Konfiguration anlegen ==="
# ============================================================
cat <<HERE > /etc/haproxy/haproxy.cfg
global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s
    user haproxy
    group haproxy
    daemon
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

# Frontend: HTTPS
frontend ft_https
    bind $IP:443 ssl crt /etc/haproxy/ssl/revproxy.pem
    mode http
    option http-keep-alive
    option forwardfor
    timeout client 30s
    # Coraza WAF via SPOE – engine-Name muss mit [coraza] in coraza.cfg uebereinstimmen
    filter spoe engine coraza config /etc/haproxy/coraza.cfg
    http-request deny deny_status 403 hdr waf-block "request" if { var(txn.coraza.action) -m str deny }
    # Security Headers
    http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"
    http-response set-header X-Frame-Options "SAMEORIGIN"
    http-response set-header X-Content-Type-Options "nosniff"
    http-response set-header Referrer-Policy "strict-origin-when-cross-origin"
    acl acl_revproxy hdr_beg(host) -i revproxy
    use_backend backend_www if acl_revproxy

# Frontend: HTTP -> HTTPS Redirect
frontend ft_http
    bind $IP:80
    mode http
    option http-keep-alive
    timeout client 30s
    acl acl_http req.proto_http
    http-request redirect code 301 scheme https if acl_http

# Backend: www-Server
backend backend_www
    stick-table type ip size 100k expire 30s store http_req_rate(10s)
    http-request track-sc0 src
    http-request deny deny_status 429 if { sc_http_req_rate(0) gt 50 }
    server www $TARGET:443 ssl verify none check

# Backend: Coraza SPOA
backend coraza-spoa
    mode tcp
    server coraza 127.0.0.1:9000
HERE

# ============================================================
echo "=== Konfiguration pruefen ==="
# ============================================================
haproxy -c -f /etc/haproxy/haproxy.cfg
if [[ $? -ne 0 ]]; then
  echo "FEHLER: haproxy.cfg ungueltig – abgebrochen!"
  exit 1
fi

echo "=== Enable und Restart ==="
systemctl enable haproxy
systemctl restart haproxy

# ============================================================
echo ""
echo "=== Fertig ==="
echo "HAProxy:       $(systemctl is-active haproxy)"
echo "Coraza SPOA:   $(systemctl is-active coraza-spoa)"
echo "Lauscht auf:   $IP :80 / :443"
echo "Backend:       $TARGET:443"
echo ""
echo "WAF testen:"
echo "  curl -vk \"https://revproxy.\$(hostname -d)?id=1'+OR+'1'='1\""
echo "  tail -f /var/log/coraza/audit.log"
