change CLI to handle global lists

This commit is contained in:
2023-12-12 19:20:22 +01:00
parent a226bc70a9
commit 5d21b81530
2 changed files with 77 additions and 72 deletions

View File

@@ -23,6 +23,7 @@ import time
from pyquarantine.config import get_milter_config, ActionConfig, ListConfig from pyquarantine.config import get_milter_config, ActionConfig, ListConfig
from pyquarantine.storage import Quarantine from pyquarantine.storage import Quarantine
from pyquarantine.list import DatabaseList
from pyquarantine import __version__ as version from pyquarantine import __version__ as version
@@ -41,8 +42,6 @@ def _get_quarantine(cfg, name, debug):
(q for q in _get_quarantines(cfg) if q["name"] == name)) (q for q in _get_quarantines(cfg) if q["name"] == name))
except StopIteration: except StopIteration:
raise RuntimeError(f"invalid quarantine '{name}'") raise RuntimeError(f"invalid quarantine '{name}'")
for name, lst in cfg["lists"].items():
cfg["lists"][name] = ListConfig(lst, {})
return Quarantine(ActionConfig(quarantine, cfg["lists"]), [], debug) return Quarantine(ActionConfig(quarantine, cfg["lists"]), [], debug)
@@ -54,12 +53,17 @@ def _get_notification(cfg, name, debug):
return notification return notification
def _get_allowlist(cfg, name, debug): def _get_list(cfg, name, debug):
allowlist = _get_quarantine(cfg, name, debug).allowlist try:
if not allowlist: list_cfg = ListConfig(cfg["lists"][name], {})
raise RuntimeError( except KeyError:
"allowlist type is set to NONE") raise RuntimeError(f"list '{name}' is not configured")
return allowlist
if list_cfg["type"] == "db":
list_cfg["loglevel"] = cfg["loglevel"]
return DatabaseList(list_cfg, debug)
else:
raise RuntimeError("invalid lists type")
def print_table(columns, rows): def print_table(columns, rows):
@@ -110,21 +114,21 @@ def list_quarantines(cfg, args):
else: else:
qlist = [] qlist = []
for q in quarantines: for q in quarantines:
cfg = q["options"] qcfg = q["options"]
storage_type = cfg["store"]["type"] storage_type = qcfg["store"]["type"]
if "notify" in cfg: if "notify" in cfg:
notification_type = cfg["notify"]["type"] notification_type = qcfg["notify"]["type"]
else: else:
notification_type = "NONE" notification_type = "NONE"
if "allowlist" in cfg: if "lists" in qcfg:
allowlist_type = cfg["allowlist"]["type"] lists_type = qcfg["lists"]
else: else:
allowlist_type = "NONE" lists_type = "NONE"
if "milter_action" in cfg: if "milter_action" in qcfg:
milter_action = cfg["milter_action"] milter_action = qcfg["milter_action"]
else: else:
milter_action = "NONE" milter_action = "NONE"
@@ -132,14 +136,14 @@ def list_quarantines(cfg, args):
"name": q["name"], "name": q["name"],
"storage": storage_type, "storage": storage_type,
"notification": notification_type, "notification": notification_type,
"allowlist": allowlist_type, "lists": lists_type,
"action": milter_action}) "action": milter_action})
print_table( print_table(
[("Name", "name"), [("Name", "name"),
("Storage", "storage"), ("Storage", "storage"),
("Notification", "notification"), ("Notification", "notification"),
("Allowlist", "allowlist"), ("Allowlist", "lists"),
("Action", "action")], ("Action", "action")],
qlist qlist
) )
@@ -193,16 +197,16 @@ def list_quarantine_emails(cfg, args):
) )
def list_allowlist(cfg, args): def list_list(cfg, args):
allowlist = _get_allowlist(cfg, args.quarantine, args.debug) lists = _get_list(cfg, args.list, args.debug)
# find allowlist entries # find lists entries
entries = allowlist.find( entries = lists.find(
mailfrom=args.mailfrom, mailfrom=args.mailfrom,
recipients=args.recipients, recipients=args.recipients,
older_than=args.older_than) older_than=args.older_than)
if not entries: if not entries:
print(f"allowlist of quarantine '{args.quarantine}' is empty") print("list is empty")
return return
# transform some values to strings # transform some values to strings
@@ -223,12 +227,12 @@ def list_allowlist(cfg, args):
) )
def add_allowlist_entry(cfg, args): def add_list_entry(cfg, args):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
allowlist = _get_allowlist(cfg, args.quarantine, args.debug) lists = _get_list(cfg, args.list, args.debug)
# check existing entries # check existing entries
entries = allowlist.check(args.mailfrom, args.recipient, logger) entries = lists.check(args.mailfrom, args.recipient, logger)
if entries: if entries:
# check if the exact entry exists already # check if the exact entry exists already
for entry in entries.values(): for entry in entries.values():
@@ -258,15 +262,15 @@ def add_allowlist_entry(cfg, args):
"from/to combination is already covered by the entries above, " "from/to combination is already covered by the entries above, "
"use --force to override.") "use --force to override.")
# add entry to allowlist # add entry to lists
allowlist.add(args.mailfrom, args.recipient, args.comment, args.permanent) lists.add(args.mailfrom, args.recipient, args.comment, args.permanent)
print("allowlist entry added successfully") print("list entry added successfully")
def delete_allowlist_entry(cfg, args): def delete_list_entry(cfg, args):
allowlist = _get_allowlist(cfg, args.quarantine, args.debug) lists = _get_list(cfg, args.list, args.debug)
allowlist.delete(args.allowlist_id) lists.delete(args.lists_id)
print("allowlist entry deleted successfully") print("list entry deleted successfully")
def notify(cfg, args): def notify(cfg, args):
@@ -524,86 +528,86 @@ def main():
help="Quarantine ID.") help="Quarantine ID.")
quar_metadata_parser.set_defaults(func=metadata) quar_metadata_parser.set_defaults(func=metadata)
# allowlist command group # lists command group
allowlist_parser = subparsers.add_parser( lists_parser = subparsers.add_parser(
"allowlist", "lists",
description="Manage allowlists.", description="Manage lists.",
help="Manage allowlists.", help="Manage lists.",
formatter_class=formatter_class) formatter_class=formatter_class)
allowlist_parser.add_argument( lists_parser.add_argument(
"quarantine",
metavar="QUARANTINE",
help="Quarantine name.")
allowlist_subparsers = allowlist_parser.add_subparsers(
dest="command",
title="Allowlist commands")
allowlist_subparsers.required = True
# allowlist list command
allowlist_list_parser = allowlist_subparsers.add_parser(
"list", "list",
description="List allowlist entries.", metavar="LIST",
help="List allowlist entries.", help="List name.")
lists_subparsers = lists_parser.add_subparsers(
dest="command",
title="Lists commands.")
lists_subparsers.required = True
# lists list command
lists_list_parser = lists_subparsers.add_parser(
"list",
description="List list entries.",
help="List list entries.",
formatter_class=formatter_class) formatter_class=formatter_class)
allowlist_list_parser.add_argument( lists_list_parser.add_argument(
"-f", "--from", "-f", "--from",
dest="mailfrom", dest="mailfrom",
help="Filter entries by from address.", help="Filter entries by from address.",
default=None, default=None,
nargs="+") nargs="+")
allowlist_list_parser.add_argument( lists_list_parser.add_argument(
"-t", "--to", "-t", "--to",
dest="recipients", dest="recipients",
help="Filter entries by recipient address.", help="Filter entries by recipient address.",
default=None, default=None,
nargs="+") nargs="+")
allowlist_list_parser.add_argument( lists_list_parser.add_argument(
"-o", "--older-than", "-o", "--older-than",
dest="older_than", dest="older_than",
help="Filter emails by last used date (days).", help="Filter emails by last used date (days).",
default=None, default=None,
type=float) type=float)
allowlist_list_parser.set_defaults(func=list_allowlist) lists_list_parser.set_defaults(func=list_list)
# allowlist add command # lists add command
allowlist_add_parser = allowlist_subparsers.add_parser( lists_add_parser = lists_subparsers.add_parser(
"add", "add",
description="Add allowlist entry.", description="Add list entry.",
help="Add allowlist entry.", help="Add list entry.",
formatter_class=formatter_class) formatter_class=formatter_class)
allowlist_add_parser.add_argument( lists_add_parser.add_argument(
"-f", "--from", "-f", "--from",
dest="mailfrom", dest="mailfrom",
help="From address.", help="From address.",
required=True) required=True)
allowlist_add_parser.add_argument( lists_add_parser.add_argument(
"-t", "--to", "-t", "--to",
dest="recipient", dest="recipient",
help="Recipient address.", help="Recipient address.",
required=True) required=True)
allowlist_add_parser.add_argument( lists_add_parser.add_argument(
"-c", "--comment", "-c", "--comment",
help="Comment.", help="Comment.",
default="added by CLI") default="added by CLI")
allowlist_add_parser.add_argument( lists_add_parser.add_argument(
"-p", "--permanent", "-p", "--permanent",
help="Add a permanent entry.", help="Add a permanent entry.",
action="store_true") action="store_true")
allowlist_add_parser.add_argument( lists_add_parser.add_argument(
"--force", "--force",
help="Force adding an entry, " help="Force adding an entry, "
"even if already covered by another entry.", "even if already covered by another entry.",
action="store_true") action="store_true")
allowlist_add_parser.set_defaults(func=add_allowlist_entry) lists_add_parser.set_defaults(func=add_list_entry)
# allowlist delete command # lists delete command
allowlist_delete_parser = allowlist_subparsers.add_parser( lists_delete_parser = lists_subparsers.add_parser(
"delete", "delete",
description="Delete allowlist entry.", description="Delete list entry.",
help="Delete allowlist entry.", help="Delete list entry.",
formatter_class=formatter_class) formatter_class=formatter_class)
allowlist_delete_parser.add_argument( lists_delete_parser.add_argument(
"allowlist_id", "lists_id",
metavar="ID", metavar="ID",
help="List ID.") help="List ID.")
allowlist_delete_parser.set_defaults(func=delete_allowlist_entry) lists_delete_parser.set_defaults(func=delete_list_entry)
args = parser.parse_args() args = parser.parse_args()

View File

@@ -299,7 +299,8 @@ class ActionConfig(BaseConfig):
return return
if "conditions" in self: if "conditions" in self:
self["conditions"] = ConditionsConfig(self["conditions"], lists) self["conditions"] = ConditionsConfig(self["conditions"], lists)
self["action"] = self.ACTION_TYPES[self["type"]](self["options"], lists) self["action"] = self.ACTION_TYPES[self["type"]](
self["options"], lists)
class RuleConfig(BaseConfig): class RuleConfig(BaseConfig):