rename whitelist to allowlist
This commit is contained in:
@@ -24,7 +24,7 @@ __all__ = [
|
|||||||
"rule",
|
"rule",
|
||||||
"run",
|
"run",
|
||||||
"storage",
|
"storage",
|
||||||
"whitelist",
|
"list",
|
||||||
"QuarantineMilter"]
|
"QuarantineMilter"]
|
||||||
|
|
||||||
__version__ = "2.0.8"
|
__version__ = "2.0.8"
|
||||||
|
|||||||
@@ -42,12 +42,12 @@ def _get_notification(quarantines, name, debug):
|
|||||||
return notification
|
return notification
|
||||||
|
|
||||||
|
|
||||||
def _get_whitelist(quarantines, name, debug):
|
def _get_allowlist(quarantines, name, debug):
|
||||||
whitelist = _get_quarantine(quarantines, name, debug).whitelist
|
allowlist = _get_quarantine(quarantines, name, debug).allowlist
|
||||||
if not whitelist:
|
if not allowlist:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"whitelist type is set to NONE")
|
"allowlist type is set to NONE")
|
||||||
return whitelist
|
return allowlist
|
||||||
|
|
||||||
|
|
||||||
def print_table(columns, rows):
|
def print_table(columns, rows):
|
||||||
@@ -105,10 +105,10 @@ def list_quarantines(quarantines, args):
|
|||||||
else:
|
else:
|
||||||
notification_type = "NONE"
|
notification_type = "NONE"
|
||||||
|
|
||||||
if "whitelist" in cfg:
|
if "allowlist" in cfg:
|
||||||
whitelist_type = cfg["whitelist"]["type"]
|
allowlist_type = cfg["allowlist"]["type"]
|
||||||
else:
|
else:
|
||||||
whitelist_type = "NONE"
|
allowlist_type = "NONE"
|
||||||
|
|
||||||
if "milter_action" in cfg:
|
if "milter_action" in cfg:
|
||||||
milter_action = cfg["milter_action"]
|
milter_action = cfg["milter_action"]
|
||||||
@@ -119,14 +119,14 @@ def list_quarantines(quarantines, args):
|
|||||||
"name": q["name"],
|
"name": q["name"],
|
||||||
"storage": storage_type,
|
"storage": storage_type,
|
||||||
"notification": notification_type,
|
"notification": notification_type,
|
||||||
"whitelist": whitelist_type,
|
"allowlist": allowlist_type,
|
||||||
"action": milter_action})
|
"action": milter_action})
|
||||||
|
|
||||||
print_table(
|
print_table(
|
||||||
[("Name", "name"),
|
[("Name", "name"),
|
||||||
("Storage", "storage"),
|
("Storage", "storage"),
|
||||||
("Notification", "notification"),
|
("Notification", "notification"),
|
||||||
("Whitelist", "whitelist"),
|
("Allowlist", "allowlist"),
|
||||||
("Action", "action")],
|
("Action", "action")],
|
||||||
qlist
|
qlist
|
||||||
)
|
)
|
||||||
@@ -180,16 +180,16 @@ def list_quarantine_emails(quarantines, args):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def list_whitelist(quarantines, args):
|
def list_allowlist(quarantines, args):
|
||||||
whitelist = _get_whitelist(quarantines, args.quarantine, args.debug)
|
allowlist = _get_allowlist(quarantines, args.quarantine, args.debug)
|
||||||
|
|
||||||
# find whitelist entries
|
# find allowlist entries
|
||||||
entries = whitelist.find(
|
entries = allowlist.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"whitelist of quarantine '{args.quarantine}' is empty")
|
print(f"allowlist of quarantine '{args.quarantine}' is empty")
|
||||||
return
|
return
|
||||||
|
|
||||||
# transform some values to strings
|
# transform some values to strings
|
||||||
@@ -210,12 +210,12 @@ def list_whitelist(quarantines, args):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def add_whitelist_entry(quarantines, args):
|
def add_allowlist_entry(quarantines, args):
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
whitelist = _get_whitelist(quarantines, args.quarantine, args.debug)
|
allowlist = _get_allowlist(quarantines, args.quarantine, args.debug)
|
||||||
|
|
||||||
# check existing entries
|
# check existing entries
|
||||||
entries = whitelist.check(args.mailfrom, args.recipient, logger)
|
entries = allowlist.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():
|
||||||
@@ -245,15 +245,15 @@ def add_whitelist_entry(quarantines, 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 whitelist
|
# add entry to allowlist
|
||||||
whitelist.add(args.mailfrom, args.recipient, args.comment, args.permanent)
|
allowlist.add(args.mailfrom, args.recipient, args.comment, args.permanent)
|
||||||
print("whitelist entry added successfully")
|
print("allowlist entry added successfully")
|
||||||
|
|
||||||
|
|
||||||
def delete_whitelist_entry(quarantines, args):
|
def delete_allowlist_entry(quarantines, args):
|
||||||
whitelist = _get_whitelist(quarantines, args.quarantine, args.debug)
|
allowlist = _get_allowlist(quarantines, args.quarantine, args.debug)
|
||||||
whitelist.delete(args.whitelist_id)
|
allowlist.delete(args.allowlist_id)
|
||||||
print("whitelist entry deleted successfully")
|
print("allowlist entry deleted successfully")
|
||||||
|
|
||||||
|
|
||||||
def notify(quarantines, args):
|
def notify(quarantines, args):
|
||||||
@@ -509,86 +509,86 @@ def main():
|
|||||||
help="Quarantine ID.")
|
help="Quarantine ID.")
|
||||||
quar_metadata_parser.set_defaults(func=metadata)
|
quar_metadata_parser.set_defaults(func=metadata)
|
||||||
|
|
||||||
# whitelist command group
|
# allowlist command group
|
||||||
whitelist_parser = subparsers.add_parser(
|
allowlist_parser = subparsers.add_parser(
|
||||||
"whitelist",
|
"allowlist",
|
||||||
description="Manage whitelists.",
|
description="Manage allowlists.",
|
||||||
help="Manage whitelists.",
|
help="Manage allowlists.",
|
||||||
formatter_class=formatter_class)
|
formatter_class=formatter_class)
|
||||||
whitelist_parser.add_argument(
|
allowlist_parser.add_argument(
|
||||||
"quarantine",
|
"quarantine",
|
||||||
metavar="QUARANTINE",
|
metavar="QUARANTINE",
|
||||||
help="Quarantine name.")
|
help="Quarantine name.")
|
||||||
whitelist_subparsers = whitelist_parser.add_subparsers(
|
allowlist_subparsers = allowlist_parser.add_subparsers(
|
||||||
dest="command",
|
dest="command",
|
||||||
title="Whitelist commands")
|
title="Allowlist commands")
|
||||||
whitelist_subparsers.required = True
|
allowlist_subparsers.required = True
|
||||||
# whitelist list command
|
# allowlist list command
|
||||||
whitelist_list_parser = whitelist_subparsers.add_parser(
|
allowlist_list_parser = allowlist_subparsers.add_parser(
|
||||||
"list",
|
"list",
|
||||||
description="List whitelist entries.",
|
description="List allowlist entries.",
|
||||||
help="List whitelist entries.",
|
help="List allowlist entries.",
|
||||||
formatter_class=formatter_class)
|
formatter_class=formatter_class)
|
||||||
whitelist_list_parser.add_argument(
|
allowlist_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="+")
|
||||||
whitelist_list_parser.add_argument(
|
allowlist_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="+")
|
||||||
whitelist_list_parser.add_argument(
|
allowlist_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)
|
||||||
whitelist_list_parser.set_defaults(func=list_whitelist)
|
allowlist_list_parser.set_defaults(func=list_allowlist)
|
||||||
# whitelist add command
|
# allowlist add command
|
||||||
whitelist_add_parser = whitelist_subparsers.add_parser(
|
allowlist_add_parser = allowlist_subparsers.add_parser(
|
||||||
"add",
|
"add",
|
||||||
description="Add whitelist entry.",
|
description="Add allowlist entry.",
|
||||||
help="Add whitelist entry.",
|
help="Add allowlist entry.",
|
||||||
formatter_class=formatter_class)
|
formatter_class=formatter_class)
|
||||||
whitelist_add_parser.add_argument(
|
allowlist_add_parser.add_argument(
|
||||||
"-f", "--from",
|
"-f", "--from",
|
||||||
dest="mailfrom",
|
dest="mailfrom",
|
||||||
help="From address.",
|
help="From address.",
|
||||||
required=True)
|
required=True)
|
||||||
whitelist_add_parser.add_argument(
|
allowlist_add_parser.add_argument(
|
||||||
"-t", "--to",
|
"-t", "--to",
|
||||||
dest="recipient",
|
dest="recipient",
|
||||||
help="Recipient address.",
|
help="Recipient address.",
|
||||||
required=True)
|
required=True)
|
||||||
whitelist_add_parser.add_argument(
|
allowlist_add_parser.add_argument(
|
||||||
"-c", "--comment",
|
"-c", "--comment",
|
||||||
help="Comment.",
|
help="Comment.",
|
||||||
default="added by CLI")
|
default="added by CLI")
|
||||||
whitelist_add_parser.add_argument(
|
allowlist_add_parser.add_argument(
|
||||||
"-p", "--permanent",
|
"-p", "--permanent",
|
||||||
help="Add a permanent entry.",
|
help="Add a permanent entry.",
|
||||||
action="store_true")
|
action="store_true")
|
||||||
whitelist_add_parser.add_argument(
|
allowlist_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")
|
||||||
whitelist_add_parser.set_defaults(func=add_whitelist_entry)
|
allowlist_add_parser.set_defaults(func=add_allowlist_entry)
|
||||||
# whitelist delete command
|
# allowlist delete command
|
||||||
whitelist_delete_parser = whitelist_subparsers.add_parser(
|
allowlist_delete_parser = allowlist_subparsers.add_parser(
|
||||||
"delete",
|
"delete",
|
||||||
description="Delete whitelist entry.",
|
description="Delete allowlist entry.",
|
||||||
help="Delete whitelist entry.",
|
help="Delete allowlist entry.",
|
||||||
formatter_class=formatter_class)
|
formatter_class=formatter_class)
|
||||||
whitelist_delete_parser.add_argument(
|
allowlist_delete_parser.add_argument(
|
||||||
"whitelist_id",
|
"allowlist_id",
|
||||||
metavar="ID",
|
metavar="ID",
|
||||||
help="Whitelist ID.")
|
help="List ID.")
|
||||||
whitelist_delete_parser.set_defaults(func=delete_whitelist_entry)
|
allowlist_delete_parser.set_defaults(func=delete_allowlist_entry)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import re
|
|||||||
|
|
||||||
from netaddr import IPAddress, IPNetwork, AddrFormatError
|
from netaddr import IPAddress, IPNetwork, AddrFormatError
|
||||||
from pyquarantine import CustomLogger
|
from pyquarantine import CustomLogger
|
||||||
from pyquarantine.whitelist import DatabaseWhitelist
|
from pyquarantine.list import DatabaseList
|
||||||
|
|
||||||
|
|
||||||
class Conditions:
|
class Conditions:
|
||||||
@@ -62,14 +62,14 @@ class Conditions:
|
|||||||
else:
|
else:
|
||||||
setattr(self, arg, cfg[arg])
|
setattr(self, arg, cfg[arg])
|
||||||
|
|
||||||
self.whitelist = cfg["whitelist"] if "whitelist" in cfg else None
|
self.allowlist = cfg["allowlist"] if "allowlist" in cfg else None
|
||||||
if self.whitelist is not None:
|
if self.allowlist is not None:
|
||||||
self.whitelist["name"] = f"{cfg['name']}: whitelist"
|
self.allowlist["name"] = f"{cfg['name']}: allowlist"
|
||||||
self.whitelist["loglevel"] = cfg["loglevel"]
|
self.allowlist["loglevel"] = cfg["loglevel"]
|
||||||
if self.whitelist["type"] == "db":
|
if self.allowlist["type"] == "db":
|
||||||
self.whitelist = DatabaseWhitelist(self.whitelist, debug)
|
self.allowlist = DatabaseList(self.allowlist, debug)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("invalid whitelist type")
|
raise RuntimeError("invalid allowlist type")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
cfg = []
|
cfg = []
|
||||||
@@ -77,12 +77,12 @@ class Conditions:
|
|||||||
"var", "metavar"):
|
"var", "metavar"):
|
||||||
if arg in self.cfg:
|
if arg in self.cfg:
|
||||||
cfg.append(f"{arg}={self.cfg[arg]}")
|
cfg.append(f"{arg}={self.cfg[arg]}")
|
||||||
if self.whitelist is not None:
|
if self.allowlist is not None:
|
||||||
cfg.append(f"whitelist={self.whitelist}")
|
cfg.append(f"allowlist={self.allowlist}")
|
||||||
return "Conditions(" + ", ".join(cfg) + ")"
|
return "Conditions(" + ", ".join(cfg) + ")"
|
||||||
|
|
||||||
def get_whitelist(self):
|
def get_allowlist(self):
|
||||||
return self.whitelist
|
return self.allowlist
|
||||||
|
|
||||||
def match_host(self, host):
|
def match_host(self, host):
|
||||||
logger = CustomLogger(
|
logger = CustomLogger(
|
||||||
@@ -124,12 +124,12 @@ class Conditions:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def get_wl_rcpts(self, mailfrom, rcpts, logger):
|
def get_wl_rcpts(self, mailfrom, rcpts, logger):
|
||||||
if not self.whitelist:
|
if not self.allowlist:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
wl_rcpts = []
|
wl_rcpts = []
|
||||||
for rcpt in rcpts:
|
for rcpt in rcpts:
|
||||||
if self.whitelist.check(mailfrom, rcpt, logger):
|
if self.allowlist.check(mailfrom, rcpt, logger):
|
||||||
wl_rcpts.append(rcpt)
|
wl_rcpts.append(rcpt)
|
||||||
|
|
||||||
return wl_rcpts
|
return wl_rcpts
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ __all__ = [
|
|||||||
"RewriteLinksConfig",
|
"RewriteLinksConfig",
|
||||||
"StoreConfig",
|
"StoreConfig",
|
||||||
"NotifyConfig",
|
"NotifyConfig",
|
||||||
"WhitelistConfig",
|
"AllowListConfig",
|
||||||
"QuarantineConfig",
|
"QuarantineConfig",
|
||||||
"ActionConfig",
|
"ActionConfig",
|
||||||
"RuleConfig",
|
"RuleConfig",
|
||||||
@@ -89,7 +89,7 @@ class BaseConfig:
|
|||||||
return self._config
|
return self._config
|
||||||
|
|
||||||
|
|
||||||
class WhitelistConfig(BaseConfig):
|
class AllowListConfig(BaseConfig):
|
||||||
JSON_SCHEMA = {
|
JSON_SCHEMA = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["type"],
|
"required": ["type"],
|
||||||
@@ -121,14 +121,14 @@ class ConditionsConfig(BaseConfig):
|
|||||||
"headers": {"type": "array",
|
"headers": {"type": "array",
|
||||||
"items": {"type": "string"}},
|
"items": {"type": "string"}},
|
||||||
"var": {"type": "string"},
|
"var": {"type": "string"},
|
||||||
"whitelist": {"type": "object"}}}
|
"allowlist": {"type": "object"}}}
|
||||||
|
|
||||||
def __init__(self, config, rec=True):
|
def __init__(self, config, rec=True):
|
||||||
super().__init__(config)
|
super().__init__(config)
|
||||||
if not rec:
|
if not rec:
|
||||||
return
|
return
|
||||||
if "whitelist" in self:
|
if "allowlist" in self:
|
||||||
self["whitelist"] = WhitelistConfig(self["whitelist"])
|
self["allowlist"] = AllowListConfig(self["allowlist"])
|
||||||
|
|
||||||
|
|
||||||
class AddHeaderConfig(BaseConfig):
|
class AddHeaderConfig(BaseConfig):
|
||||||
@@ -242,7 +242,7 @@ class QuarantineConfig(BaseConfig):
|
|||||||
"notify": {"type": "object"},
|
"notify": {"type": "object"},
|
||||||
"milter_action": {"type": "string"},
|
"milter_action": {"type": "string"},
|
||||||
"reject_reason": {"type": "string"},
|
"reject_reason": {"type": "string"},
|
||||||
"whitelist": {"type": "object"},
|
"allowlist": {"type": "object"},
|
||||||
"store": {"type": "object"},
|
"store": {"type": "object"},
|
||||||
"smtp_host": {"type": "string"},
|
"smtp_host": {"type": "string"},
|
||||||
"smtp_port": {"type": "number"}}}
|
"smtp_port": {"type": "number"}}}
|
||||||
@@ -256,9 +256,9 @@ class QuarantineConfig(BaseConfig):
|
|||||||
self["store"] = StoreConfig(self["store"])
|
self["store"] = StoreConfig(self["store"])
|
||||||
if "notify" in self:
|
if "notify" in self:
|
||||||
self["notify"] = NotifyConfig(self["notify"])
|
self["notify"] = NotifyConfig(self["notify"])
|
||||||
if "whitelist" in self:
|
if "allowlist" in self:
|
||||||
self["whitelist"] = ConditionsConfig(
|
self["allowlist"] = ConditionsConfig(
|
||||||
{"whitelist": self["whitelist"]}, rec)
|
{"allowlist": self["allowlist"]}, rec)
|
||||||
|
|
||||||
|
|
||||||
class ActionConfig(BaseConfig):
|
class ActionConfig(BaseConfig):
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"DatabaseWhitelist",
|
"DatabaseList",
|
||||||
"WhitelistBase"]
|
"ListBase"]
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import peewee
|
import peewee
|
||||||
@@ -24,8 +24,8 @@ from datetime import datetime
|
|||||||
from playhouse.db_url import connect
|
from playhouse.db_url import connect
|
||||||
|
|
||||||
|
|
||||||
class WhitelistBase:
|
class ListBase:
|
||||||
"Whitelist base class"
|
"List base class"
|
||||||
def __init__(self, cfg, debug):
|
def __init__(self, cfg, debug):
|
||||||
self.cfg = cfg
|
self.cfg = cfg
|
||||||
self.logger = logging.getLogger(cfg["name"])
|
self.logger = logging.getLogger(cfg["name"])
|
||||||
@@ -47,15 +47,15 @@ class WhitelistBase:
|
|||||||
return self.batv_regex.sub(r"\g<LEFT_PART>@", addr, count=1)
|
return self.batv_regex.sub(r"\g<LEFT_PART>@", addr, count=1)
|
||||||
|
|
||||||
def check(self, mailfrom, recipient):
|
def check(self, mailfrom, recipient):
|
||||||
"Check if mailfrom/recipient combination is whitelisted."
|
"Check if mailfrom/recipient combination is listed."
|
||||||
return
|
return
|
||||||
|
|
||||||
def find(self, mailfrom=None, recipients=None, older_than=None):
|
def find(self, mailfrom=None, recipients=None, older_than=None):
|
||||||
"Find whitelist entries."
|
"Find list entries."
|
||||||
return
|
return
|
||||||
|
|
||||||
def add(self, mailfrom, recipient, comment, permanent):
|
def add(self, mailfrom, recipient, comment, permanent):
|
||||||
"Add entry to whitelist."
|
"Add entry to list."
|
||||||
# check if mailfrom and recipient are valid
|
# check if mailfrom and recipient are valid
|
||||||
if not self.valid_entry_regex.match(mailfrom):
|
if not self.valid_entry_regex.match(mailfrom):
|
||||||
raise RuntimeError("invalid from address")
|
raise RuntimeError("invalid from address")
|
||||||
@@ -63,12 +63,12 @@ class WhitelistBase:
|
|||||||
raise RuntimeError("invalid recipient")
|
raise RuntimeError("invalid recipient")
|
||||||
return
|
return
|
||||||
|
|
||||||
def delete(self, whitelist_id):
|
def delete(self, list_id):
|
||||||
"Delete entry from whitelist."
|
"Delete entry from list."
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
class WhitelistModel(peewee.Model):
|
class DatabaseListModel(peewee.Model):
|
||||||
mailfrom = peewee.CharField()
|
mailfrom = peewee.CharField()
|
||||||
recipient = peewee.CharField()
|
recipient = peewee.CharField()
|
||||||
created = peewee.DateTimeField(default=datetime.now)
|
created = peewee.DateTimeField(default=datetime.now)
|
||||||
@@ -84,9 +84,9 @@ class Meta:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class DatabaseWhitelist(WhitelistBase):
|
class DatabaseList(ListBase):
|
||||||
"Whitelist class to store whitelist in a database"
|
"List class to store lists in a database"
|
||||||
whitelist_type = "db"
|
list_type = "db"
|
||||||
_db_connections = {}
|
_db_connections = {}
|
||||||
_db_tables = {}
|
_db_tables = {}
|
||||||
|
|
||||||
@@ -96,8 +96,8 @@ class DatabaseWhitelist(WhitelistBase):
|
|||||||
tablename = cfg["table"]
|
tablename = cfg["table"]
|
||||||
connection_string = cfg["connection"]
|
connection_string = cfg["connection"]
|
||||||
|
|
||||||
if connection_string in DatabaseWhitelist._db_connections.keys():
|
if connection_string in DatabaseList._db_connections.keys():
|
||||||
db = DatabaseWhitelist._db_connections[connection_string]
|
db = DatabaseList._db_connections[connection_string]
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
# connect to database
|
# connect to database
|
||||||
@@ -112,22 +112,22 @@ class DatabaseWhitelist(WhitelistBase):
|
|||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"unable to connect to database: {e}")
|
f"unable to connect to database: {e}")
|
||||||
|
|
||||||
DatabaseWhitelist._db_connections[connection_string] = db
|
DatabaseList._db_connections[connection_string] = db
|
||||||
|
|
||||||
# generate model meta class
|
# generate model meta class
|
||||||
self.meta = Meta
|
self.meta = Meta
|
||||||
self.meta.database = db
|
self.meta.database = db
|
||||||
self.meta.table_name = tablename
|
self.meta.table_name = tablename
|
||||||
self.model = type(
|
self.model = type(
|
||||||
f"WhitelistModel_{self.cfg['name']}",
|
f"DatabaseListModel_{self.cfg['name']}",
|
||||||
(WhitelistModel,),
|
(DatabaseListModel,),
|
||||||
{"Meta": self.meta})
|
{"Meta": self.meta})
|
||||||
|
|
||||||
if connection_string not in DatabaseWhitelist._db_tables.keys():
|
if connection_string not in DatabaseList._db_tables.keys():
|
||||||
DatabaseWhitelist._db_tables[connection_string] = []
|
DatabaseList._db_tables[connection_string] = []
|
||||||
|
|
||||||
if tablename not in DatabaseWhitelist._db_tables[connection_string]:
|
if tablename not in DatabaseList._db_tables[connection_string]:
|
||||||
DatabaseWhitelist._db_tables[connection_string].append(tablename)
|
DatabaseList._db_tables[connection_string].append(tablename)
|
||||||
try:
|
try:
|
||||||
db.create_tables([self.model])
|
db.create_tables([self.model])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -139,7 +139,7 @@ class DatabaseWhitelist(WhitelistBase):
|
|||||||
for arg in ("connection", "table"):
|
for arg in ("connection", "table"):
|
||||||
if arg in self.cfg:
|
if arg in self.cfg:
|
||||||
cfg.append(f"{arg}={self.cfg[arg]}")
|
cfg.append(f"{arg}={self.cfg[arg]}")
|
||||||
return "DatabaseWhitelist(" + ", ".join(cfg) + ")"
|
return "DatabaseList(" + ", ".join(cfg) + ")"
|
||||||
|
|
||||||
def _entry_to_dict(self, entry):
|
def _entry_to_dict(self, entry):
|
||||||
result = {}
|
result = {}
|
||||||
@@ -164,14 +164,14 @@ class DatabaseWhitelist(WhitelistBase):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
def check(self, mailfrom, recipient, logger):
|
def check(self, mailfrom, recipient, logger):
|
||||||
# check if mailfrom/recipient combination is whitelisted
|
# check if mailfrom/recipient combination is listed
|
||||||
super().check(mailfrom, recipient)
|
super().check(mailfrom, recipient)
|
||||||
mailfrom = self.remove_batv(mailfrom)
|
mailfrom = self.remove_batv(mailfrom)
|
||||||
recipient = self.remove_batv(recipient)
|
recipient = self.remove_batv(recipient)
|
||||||
|
|
||||||
# generate list of possible mailfroms
|
# generate list of possible mailfroms
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"query database for whitelist entries from <{mailfrom}> "
|
f"query database for list entries from <{mailfrom}> "
|
||||||
f"to <{recipient}>")
|
f"to <{recipient}>")
|
||||||
mailfroms = [""]
|
mailfroms = [""]
|
||||||
if "@" in mailfrom and not mailfrom.startswith("@"):
|
if "@" in mailfrom and not mailfrom.startswith("@"):
|
||||||
@@ -196,7 +196,7 @@ class DatabaseWhitelist(WhitelistBase):
|
|||||||
raise RuntimeError(f"unable to query database: {e}")
|
raise RuntimeError(f"unable to query database: {e}")
|
||||||
|
|
||||||
if not entries:
|
if not entries:
|
||||||
# no whitelist entry found
|
# no list entry found
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
if len(entries) > 1:
|
if len(entries) > 1:
|
||||||
@@ -213,7 +213,7 @@ class DatabaseWhitelist(WhitelistBase):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def find(self, mailfrom=None, recipients=None, older_than=None):
|
def find(self, mailfrom=None, recipients=None, older_than=None):
|
||||||
"Find whitelist entries."
|
"Find list entries."
|
||||||
super().find(mailfrom, recipients, older_than)
|
super().find(mailfrom, recipients, older_than)
|
||||||
|
|
||||||
if isinstance(mailfrom, str):
|
if isinstance(mailfrom, str):
|
||||||
@@ -244,7 +244,7 @@ class DatabaseWhitelist(WhitelistBase):
|
|||||||
return entries
|
return entries
|
||||||
|
|
||||||
def add(self, mailfrom, recipient, comment, permanent):
|
def add(self, mailfrom, recipient, comment, permanent):
|
||||||
"Add entry to whitelist."
|
"Add entry to list."
|
||||||
super().add(
|
super().add(
|
||||||
mailfrom,
|
mailfrom,
|
||||||
recipient,
|
recipient,
|
||||||
@@ -263,16 +263,16 @@ class DatabaseWhitelist(WhitelistBase):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeError(f"unable to add entry to database: {e}")
|
raise RuntimeError(f"unable to add entry to database: {e}")
|
||||||
|
|
||||||
def delete(self, whitelist_id):
|
def delete(self, list_id):
|
||||||
"Delete entry from whitelist."
|
"Delete entry from list."
|
||||||
super().delete(whitelist_id)
|
super().delete(list_id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
query = self.model.delete().where(self.model.id == whitelist_id)
|
query = self.model.delete().where(self.model.id == list_id)
|
||||||
deleted = query.execute()
|
deleted = query.execute()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"unable to delete entry from database: {e}")
|
f"unable to delete entry from database: {e}")
|
||||||
|
|
||||||
if deleted == 0:
|
if deleted == 0:
|
||||||
raise RuntimeError("invalid whitelist id")
|
raise RuntimeError("invalid list id")
|
||||||
@@ -203,14 +203,14 @@ class EMailNotification(BaseNotification):
|
|||||||
f"and its content")
|
f"and its content")
|
||||||
element.extract()
|
element.extract()
|
||||||
|
|
||||||
# remove not whitelisted elements, but keep their content
|
# remove not allowed elements, but keep their content
|
||||||
for element in soup.find_all(True):
|
for element in soup.find_all(True):
|
||||||
if element.name not in EMailNotification._good_tags:
|
if element.name not in EMailNotification._good_tags:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"removing tag '{element.name}', keep its content")
|
f"removing tag '{element.name}', keep its content")
|
||||||
element.replaceWithChildren()
|
element.replaceWithChildren()
|
||||||
|
|
||||||
# remove not whitelisted attributes
|
# remove not allowed attributes
|
||||||
for element in soup.find_all(True):
|
for element in soup.find_all(True):
|
||||||
for attribute in list(element.attrs.keys()):
|
for attribute in list(element.attrs.keys()):
|
||||||
if attribute not in EMailNotification._good_attributes:
|
if attribute not in EMailNotification._good_attributes:
|
||||||
|
|||||||
@@ -428,13 +428,13 @@ class Quarantine:
|
|||||||
"options": cfg["options"]["notify"].get_config()})
|
"options": cfg["options"]["notify"].get_config()})
|
||||||
self._notification = Notify(notify_cfg, local_addrs, debug)
|
self._notification = Notify(notify_cfg, local_addrs, debug)
|
||||||
|
|
||||||
self._whitelist = None
|
self._allowlist = None
|
||||||
if "whitelist" in cfg["options"]:
|
if "allowlist" in cfg["options"]:
|
||||||
whitelist_cfg = cfg["options"]["whitelist"]
|
allowlist_cfg = cfg["options"]["allowlist"]
|
||||||
whitelist_cfg["name"] = cfg["name"]
|
allowlist_cfg["name"] = cfg["name"]
|
||||||
whitelist_cfg["loglevel"] = cfg["loglevel"]
|
allowlist_cfg["loglevel"] = cfg["loglevel"]
|
||||||
self._whitelist = Conditions(
|
self._allowlist = Conditions(
|
||||||
whitelist_cfg,
|
allowlist_cfg,
|
||||||
local_addrs=[],
|
local_addrs=[],
|
||||||
debug=debug)
|
debug=debug)
|
||||||
|
|
||||||
@@ -456,8 +456,8 @@ class Quarantine:
|
|||||||
cfg.append(f"store={str(self._storage)}")
|
cfg.append(f"store={str(self._storage)}")
|
||||||
if self._notification is not None:
|
if self._notification is not None:
|
||||||
cfg.append(f"notify={str(self._notification)}")
|
cfg.append(f"notify={str(self._notification)}")
|
||||||
if self._whitelist is not None:
|
if self._allowlist is not None:
|
||||||
cfg.append(f"whitelist={str(self._whitelist)}")
|
cfg.append(f"allowlist={str(self._allowlist)}")
|
||||||
for key in ["milter_action", "reject_reason"]:
|
for key in ["milter_action", "reject_reason"]:
|
||||||
if key not in self.cfg["options"]:
|
if key not in self.cfg["options"]:
|
||||||
continue
|
continue
|
||||||
@@ -481,10 +481,10 @@ class Quarantine:
|
|||||||
return self._notification.get_notification()
|
return self._notification.get_notification()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def whitelist(self):
|
def allowlist(self):
|
||||||
if self._whitelist is None:
|
if self._allowlist is None:
|
||||||
return None
|
return None
|
||||||
return self._whitelist.get_whitelist()
|
return self._allowlist.get_allowlist()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def milter_action(self):
|
def milter_action(self):
|
||||||
@@ -554,14 +554,14 @@ class Quarantine:
|
|||||||
self.logger, {"name": self.cfg["name"], "qid": milter.qid})
|
self.logger, {"name": self.cfg["name"], "qid": milter.qid})
|
||||||
rcpts = milter.msginfo["rcpts"]
|
rcpts = milter.msginfo["rcpts"]
|
||||||
wl_rcpts = []
|
wl_rcpts = []
|
||||||
if self._whitelist:
|
if self._allowlist:
|
||||||
wl_rcpts = self._whitelist.get_wl_rcpts(
|
wl_rcpts = self._allowlist.get_wl_rcpts(
|
||||||
milter.msginfo["mailfrom"], rcpts, logger)
|
milter.msginfo["mailfrom"], rcpts, logger)
|
||||||
if wl_rcpts:
|
if wl_rcpts:
|
||||||
logger.info(f"whitelisted recipients: {wl_rcpts}")
|
logger.info(f"allowed recipients: {wl_rcpts}")
|
||||||
rcpts = [rcpt for rcpt in rcpts if rcpt not in wl_rcpts]
|
rcpts = [rcpt for rcpt in rcpts if rcpt not in wl_rcpts]
|
||||||
if not rcpts:
|
if not rcpts:
|
||||||
# all recipients whitelisted
|
# all recipients allowed
|
||||||
return
|
return
|
||||||
milter.msginfo["rcpts"] = rcpts.copy()
|
milter.msginfo["rcpts"] = rcpts.copy()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user