????
Current Path : /opt/imunify360/venv/lib/python3.11/site-packages/im360/model/ |
Current File : //opt/imunify360/venv/lib/python3.11/site-packages/im360/model/whitelisted_domains.py |
import os import re import shlex from im360.subsys.webshield import service_reload _DOMAIN_PATTERN = re.compile( r"^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|" r"([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|" r"([a-zA-Z0-9][-_.a-zA-Z0-9]{0,61}[a-zA-Z0-9]))\." r"([a-zA-Z]{2,13}|[a-zA-Z0-9-]{2,30}.[a-zA-Z]{2,3})$" ) class _Comment: @classmethod def parse(cls, raw): raw = raw.strip() if not raw.startswith("#"): return message = raw.lstrip("#") message = message.strip() return cls(message) def __init__(self, message): self.message = message def __repr__(self): return "<Comment({message})>".format(message=repr(self.message)) def __str__(self): return "# {message}".format(message=self.message) class Host: @classmethod def parse(cls, raw): data = shlex.split(raw) try: name, state = data[:2] except ValueError: return state = state.rstrip(";") state = 0 if state in ("", "0") else 1 try: return cls(name, state) except ValueError: return def __init__(self, name, state=1): if not _DOMAIN_PATTERN.match(name): raise ValueError("Invalid host name: {0}".format(name)) self.name = name self.state = state def __eq__(self, other): return self.name == other.name def __hash__(self): return hash(self.name) def __repr__(self): return "<Host({name}, {state})>".format( name=repr(self.name), state=self.state ) def __str__(self): return "{name} {state};".format(name=self.name, state=self.state) class _Empty: @classmethod def parse(cls, raw): assert not raw.strip() return cls() def __repr__(self): return "<Empty()>" def __str__(self): return "" class _WhitelistedDomainsConfig: WHITELISTED_DOMAINS_CONF = ( "/etc/imunify360-webshield/whitelisted-domains.conf" ) @classmethod def read(cls, filename=None): lines = [] with open(filename or cls.WHITELISTED_DOMAINS_CONF) as r: for _line in r: try: line = ( Host.parse(_line) or _Comment.parse(_line) or _Empty.parse(_line) ) except AssertionError: raise ValueError("Error parsing line: {l}".format(l=_line)) lines.append(line) return cls(lines) @property def list(self): return [line for line in self.lines if isinstance(line, Host)] def __init__(self, lines): self.lines = lines def _last_empty(self): if len(self.lines) == 0: return if not isinstance(self.lines[-1], (_Empty, Host)): self.lines.append(_Empty()) def add(self, host): if host in self.list: raise ValueError( "Domain already whitelisted: {}".format(host.name) ) self._last_empty() self.lines.append(host) def flush(self): lines = [line for line in self.lines if not isinstance(line, Host)] self.lines = lines def remove(self, host): if host not in self.list: return lines = [] for line in self.lines: if isinstance(line, Host) and line == host: continue lines.append(line) while isinstance(lines[-1], _Empty): lines = lines[:-1] self.lines = lines def sync(self, hosts): self.flush() self._last_empty() self.lines.extend(set(hosts)) def write(self, filename=None): with open(filename or self.WHITELISTED_DOMAINS_CONF, "w") as w: for line in self.lines: w.write(str(line) + os.linesep) def get_list(): wl = _WhitelistedDomainsConfig.read() return [li.name for li in wl.list] async def add_domain(domain): wl = _WhitelistedDomainsConfig.read() wl.add(Host(domain)) wl.write() await service_reload() async def del_domain(domain): wl = _WhitelistedDomainsConfig.read() wl.remove(Host(domain)) wl.write() await service_reload() async def reset_domains(domains): wl = _WhitelistedDomainsConfig.read() wl.sync([Host(d) for d in domains]) wl.write() await service_reload()