Be able to show current bans

This commit is contained in:
László Károlyi 2024-08-06 23:57:08 +02:00
parent d230f8cfde
commit 1122ab9843
Signed by: karolyi
GPG key ID: 2DCAF25E55735BFE

View file

@ -13,15 +13,27 @@ from sys import stderr
from tempfile import gettempdir from tempfile import gettempdir
from threading import Thread from threading import Thread
from types import FrameType from types import FrameType
from typing import NamedTuple from typing import Literal, NamedTuple
_F2B_DBPATH = Path('/', 'var', 'db', 'fail2ban', 'fail2ban.sqlite3') _F2B_DBPATH = Path('/', 'var', 'db', 'fail2ban', 'fail2ban.sqlite3')
_CONFIG_RESULT = """\ _CONFIG_RESULT_ALL = """\
graph_category fail2ban graph_category fail2ban
graph_title {db_table} DB table statistics graph_title {db_table} DB table statistics - ALL RECORDS
graph_vlabel Database record count by jail name graph_vlabel Database record count by jail name
graph_printf %3.0lf graph_printf %3.0lf
""" """
_CONFIG_RESULT_CURRENT = """\
graph_category fail2ban
graph_title {db_table} DB table statistics - CURRENTLY BANNED
graph_vlabel Currently banned IPs by jail name
graph_printf %3.0lf
"""
_DB_QUERY_ALL = (
'SELECT `jail`, COUNT(*) FROM `{db_table}` WHERE `jail` IN ({in_clause}) '
'GROUP BY `jail`')
_DB_QUERY_CURRENT = (
'SELECT `jail`, COUNT(*) FROM `{db_table}` WHERE `timeofban` + `bantime` '
'> UNIXEPOCH() AND `jail` IN ({in_clause}) GROUP BY `jail`')
def _log_message(message: str) -> None: def _log_message(message: str) -> None:
@ -72,24 +84,26 @@ class F2bRemoteRequestHandler(SimpleHTTPRequestHandler):
self.end_headers() self.end_headers()
self.wfile.write(body_bytes) self.wfile.write(body_bytes)
def __get_config(self, db_table: str) -> None: def __get_config(
self, db_table: str, qtype: Literal['all', 'current']) -> None:
'Send the current plugin configuration for `db_table`.' 'Send the current plugin configuration for `db_table`.'
message = _CONFIG_RESULT.format(db_table=db_table) template = \
_CONFIG_RESULT_ALL if qtype == 'all' else _CONFIG_RESULT_CURRENT
message = template.format(db_table=db_table)
for jail in self.__get_jails(): for jail in self.__get_jails():
message += f'usercount{jail.id}.label {jail.name}\n' message += f'usercount{jail.id}.label {jail.name}\n'
message += f'usercount{jail.id}.draw LINE1\n' message += f'usercount{jail.id}.draw LINE1\n'
self.__send_data_response(body=message) self.__send_data_response(body=message)
def __get_data(self, db_table: str) -> None: def __get_data(
self, db_table: str, qtype: Literal['all', 'current']) -> None:
'Return organized data for the requested `db_table`.' 'Return organized data for the requested `db_table`.'
output = '' output = ''
cursor = self.__connection.cursor() cursor = self.__connection.cursor()
jails = self.__get_jails() jails = self.__get_jails()
in_clause = ', '.join(f'\'{jail.name}\'' for jail in jails) in_clause = ', '.join(f'\'{jail.name}\'' for jail in jails)
db_query = ( template = _DB_QUERY_ALL if qtype == 'all' else _DB_QUERY_CURRENT
f'SELECT `jail`, COUNT(*) FROM `{db_table}` WHERE `jail` IN ' cursor.execute(template.format(db_table=db_table, in_clause=in_clause))
f'({in_clause}) GROUP BY `jail`')
cursor.execute(db_query)
result = dict[str, int]() result = dict[str, int]()
while row := cursor.fetchone(): while row := cursor.fetchone():
jail_name, count = row jail_name, count = row
@ -103,15 +117,23 @@ class F2bRemoteRequestHandler(SimpleHTTPRequestHandler):
def do_GET(self) -> None: def do_GET(self) -> None:
'Overwriting `do_GET`.' 'Overwriting `do_GET`.'
self.__connection = connect(database=_F2B_DBPATH) self.__connection = connect(database=_F2B_DBPATH)
match(self.path): match self.path:
case '/db/bans/config/': case '/db-all/bans/config/':
self.__get_config(db_table='bans') self.__get_config(db_table='bans', qtype='all')
case '/db/bips/config/': case '/db-all/bips/config/':
self.__get_config(db_table='bips') self.__get_config(db_table='bips', qtype='all')
case '/db/bans/data/': case '/db-all/bans/data/':
self.__get_data(db_table='bans') self.__get_data(db_table='bans', qtype='all')
case '/db/bips/data/': case '/db-all/bips/data/':
self.__get_data(db_table='bips') self.__get_data(db_table='bips', qtype='all')
case '/db-current/bans/config/':
self.__get_config(db_table='bans', qtype='current')
case '/db-current/bips/config/':
self.__get_config(db_table='bips', qtype='current')
case '/db-current/bans/data/':
self.__get_data(db_table='bans', qtype='current')
case '/db-current/bips/data/':
self.__get_data(db_table='bips', qtype='current')
case _: case _:
self.__send_403() self.__send_403()
self.__connection.close() self.__connection.close()