#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-05-05; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu

set -Ceuo pipefail

#######################################
# Wrapper for fail2ban filter checks against logs.
# Usage: f2bchk --mode=ignored || --mode=matched  || --mode=missed \
#               --filter=/etc/fail2ban/filter.d/ufw.aggressive.conf \
#               --log=/var/log/ufw.log \
#               --output=/tmp/f2bchk.log
# Globals:
#   CGRE
#   CRED
#   CRES
#   NL
# Arguments:
#   None
# Returns:
#   0: on success
#   1: In case of any errors
#######################################
f2bchk(){
  ### Declare default values (readonly)
  declare -r DEFAULT_MODE="matched"
  declare -r DEFAULT_FILTER="/etc/fail2ban/filter.d/ufw.aggressive.conf"
  declare -r DEFAULT_LOG="/var/log/ufw.log"

  declare mode="${DEFAULT_MODE}"
  declare filter="${DEFAULT_FILTER}"
  declare log="${DEFAULT_LOG}"
  declare output=""
  declare arg=""

  for arg in "$@"; do
    case "${arg}" in
      --mode=*)   mode="${arg#--mode=}";;
      --filter=*) filter="${arg#--filter=}";;
      --log=*)    log="${arg#--log=}";;
      --output=*) output="${arg#--output=}";;
      *)
        printf "%s[ERROR]%s Unknown argument: '%s' %s" "${CRED}" "${CRES}" "${arg}" "${CRED}"
        return 1
        ;;
    esac
  done

  declare flag suffix
  case "${mode}" in
    ignored) flag="--print-all-ignored"; suffix="all.ignored";;
    matched) flag="--print-all-matched"; suffix="all.matched";;
    missed)  flag="--print-all-missed";  suffix="all.missed";;
    *)
      printf "%s[ERROR]%s Invalid mode: '%s' %s" "${CRED}" "${CRES}" "${mode}" "${NL}"
      return 1
      ;;
  esac

  if [[ -z "${output}" ]]; then
    declare filter_name="${filter##*/}"
    filter_name="${filter_name%.conf}"
    output="/tmp/${filter_name}.${suffix}.log"
  fi

  if [[ ! -r "${log}" ]]; then
    printf "%s[ERROR]%s Log file '%s' not found or not readable. %s" "${CRED}" "${CRES}" "${log}" "${NL}"
    return 1
  fi

  if [[ ! -r "${filter}" ]]; then
    printf "%s[ERROR]%s Filter file '%s' not found or not readable. %s" "${CRED}" "${CRES}" "${filter}" "${NL}"
    return 1
  fi

  printf "%s[INFO]%s Running: fail2ban-regex '%s %s %s' %s" "${CGRE}" "${CRES}" "${log}" "${filter}" "${flag}" "${NL}"

  if fail2ban-regex "${log}" "${filter}" "${flag}" >| "${output}"; then

    printf "%s[SUCCESS]%s Saved log to: '%s' %s" "${CGRE}" "${CRES}" "${output}" "${NL}"
    printf "You can view it with: cat %s%s" "${output}" "${NL}"
  else

    printf "%s[ERROR]%s fail2ban-regex execution failed. %s" "${CRED}" "${CRES}" "${NL}"
    return 1

  fi

  exit 0
}
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
