2
     ʾh      2
     481           Ua@~b~Ӊ-9Qϓ,$ٰ;1g}ZXK`'7M	{<N?waJ?O'v ~& "QB#lPEtD>8:ĮDIrH	YXTgbk9XDijC} 3jn2rW}ɲ+V*Uh9ÈlE7阢(\v[3Zxv8(D1,||*HJjNԘ@IP(	M2Q:R"{!ūem߻亨υU)@[@^jJ!J79wk"GrT.n8e-^}vzC#C+ľФhMLye]\!ZV1gl\tswP]ߟUo4w_8A[4    (   lzC]q@q\jbѿy #    #!/opt/imunify360/venv/bin/python3
"""
The watchdog script that checks the webshield and restarts it if error found
"""

import json
import logging
import logging.handlers
import os
import requests
import subprocess
import sys
import uuid
from time import ctime, time, sleep
from argparse import ArgumentParser
from traceback import format_exception
from types import TracebackType


import sentry_sdk
from sentry_sdk import configure_scope


log = logging.getLogger(__name__)


def _syslog_exception(etype: type[Exception], evalue: Exception, etb: TracebackType):
    try:
        log.error('%s', ''.join(format_exception(etype, evalue, etb)).rstrip())
    except BaseException:
        try:
            sys.stderr.write('Error reporting error\n')
            sys.stderr.flush()
        except BaseException:
            pass


def _setup_logging(debug: bool, to_stderr: bool):
    logging.raiseExceptions = False
    logging.captureWarnings(True)
    sys.excepthook = _syslog_exception
    if to_stderr:
        handler = logging.StreamHandler()
        msgfmt = '%(asctime)s %(levelname)s: %(message)s'
    else:
        handler = logging.handlers.SysLogHandler('/dev/log')
        msgfmt = 'imunify360-watchdog: %(levelname)s: %(message)s'
    handler.setFormatter(logging.Formatter(msgfmt))
    logging.getLogger().addHandler(handler)
    logging.getLogger().setLevel(logging.DEBUG if debug else logging.INFO)


class Watchdog:
    request_timeout = 4
    subprocess_timeout = 30
    user_agent = 'Webshield-watchdog-agent'
    sentry_dsn_path = '/usr/share/imunify360-webshield/sentry'
    package_name = 'imunify360-webshield-bundle'
    license_path = '/var/imunify360/license.json'
    flag_path = '/var/imunify360/webshield_broken'
    wafd_sock_path = '/var/run/imunify360/libiplists-daemon.sock'
    wafd_check_binary = 'i360_wafd_check'

    def __init__(self, status):
        platform = status.get('platform', {})
        self.should_proxy_be_running = platform.get('should_proxy_be_running', False)
        units = status.get('units', {})
        self.is_running = units.get('imunify360-webshield', {}).get('active', False)
        self.sentry_dsn = self._get_dsn()
        self.__show_flag_status()

    def __show_flag_status(self):
        if (ts := self._get_flag_timestamp()) is None:
            log.info("Flag '%s' is not set", self.flag_path)
        else:
            log.info("Flag '%s' is set on %s, now is %s", self.flag_path, ctime(ts), ctime(time()))

    @classmethod
    def _get_server_id(cls):
        try:
            with open(cls.license_path) as f:
                data = json.load(f)
        except Exception:
            return 'none'
        return data.get('id', 'none')

    @classmethod
    def _get_dsn(cls):
        try:
            with open(cls.sentry_dsn_path) as f:
                return f.read().strip()
        except Exception:
            return

    def _init_sentry(self):
        sentry_sdk.init(dsn=self.sentry_dsn, release=self._imunify360_version())
        with configure_scope() as scope:
            scope.user = {'id': self._get_server_id()}

    def _make_http_request(self, i: int, port: int):
        url = f'http://0.0.0.0:{port}/selfcheck?uuid={uuid.uuid4()}'
        curr_timeout = self.request_timeout * i
        try:
            requests.get(url, headers={'User-Agent': self.user_agent}, allow_redirects=False, timeout=curr_timeout)
        except Exception as error:
            log.debug("Webshield is not a