#!/usr/bin/env bash
# validasi-ruleset.sh — periksa struktur ruleset nftables sebelum diterapkan.
#
# Pemakaian:
#   validasi-ruleset.sh <ruleset.nft>
#
# Pemeriksaan memakai grep pada bentuk baku yang kita sepakati di
# proyek ini; ubah daftar port = ubah ruleset, kebijakan-port.txt,
# dan pola dport di bawah ini bersama-sama.
#
# Kode keluar:
#   0  seluruh pemeriksaan lolos
#   N  jumlah pemeriksaan yang gagal
#   1  berkas ruleset tidak ditemukan

set -u

berkas=${1:-}
if [ -z "$berkas" ] || [ ! -f "$berkas" ]; then
    printf 'validasi-ruleset.sh: berkas ruleset tidak ditemukan: %s\n' \
        "$berkas" >&2
    exit 1
fi

gagal=0

# periksa <pola> <pesan>: pola harus ditemukan.
periksa() {
    if grep -qE -- "$1" "$berkas"; then
        printf 'OK    %s\n' "$2"
    else
        printf 'GAGAL %s\n' "$2"
        gagal=$((gagal + 1))
    fi
}

# tolak <pola> <pesan>: pola justru tidak boleh ada.
tolak() {
    if grep -qE -- "$1" "$berkas"; then
        printf 'GAGAL %s\n' "$2"
        gagal=$((gagal + 1))
    else
        printf 'OK    %s\n' "$2"
    fi
}

periksa '^#!/usr/sbin/nft -f' 'shebang nft -f (bisa dieksekusi langsung)'
periksa '^flush ruleset' 'ruleset lama dibuang dulu (flush ruleset)'
periksa '^table inet filter' 'table inet filter dideklarasikan'
periksa 'policy drop;' 'kebijakan chain input: drop'
periksa 'iifname "lo" accept' 'loopback diizinkan'
periksa 'ct state established,related accept' 'balasan koneksi sah diizinkan'
periksa 'tcp dport \{ 22, 80, 443 \} accept' 'hanya SSH, HTTP, HTTPS yang dibuka'
periksa 'limit rate .* log prefix' 'paket yang jatuh ke policy dicatat dengan rem'
tolak 'policy accept;' 'tidak ada kebijakan accept yang menyelip'
tolak '^[[:space:]]*accept[[:space:]]*$' 'tidak ada aturan accept tanpa syarat'

exit "$gagal"
