Ejemplo n.º 1
0
class TestFirstrun(unittest.TestCase):
    """TODO: Doku."""
    def setUp(self) -> None:
        """TODO: Doku."""
        prepare_configuration()
        self.config = Config(WEB_CONFIG_PATH)
        self.config.set_value("WEB", "username", "")
        self.config.set_value("WEB", "password", "")
        self.client = prepare_client()

    def tearDown(self) -> None:
        """TODO: Doku."""
        restore_configuration()

    def test_firstrun_logged_out(self) -> None:
        """TODO: Doku."""
        response = self.client.get('/')
        self.assertIn(b"username and password", response.data)

    def test_firstrun_save_logged_out(self) -> None:
        """TODO: Doku."""
        response = self.client.post('/firstrun',
                                    data={
                                        "username": "******",
                                        "password": "******",
                                        "password-confirm": "demo"
                                    },
                                    follow_redirects=True)
        self.assertIn(b"Username and password have been successfully saved",
                      response.data)
Ejemplo n.º 2
0
class Passwd(object):
    """the class contains the password generation and saving"""

    def __init__(self):
        """the init function creates the config variable and calls the user input"""
        self.config = Config("config/web.ini")
        self.ask_user()

    def savepasswd(self, password):
        """the function saves the password into the config file using the config class"""
        hostname = platform.node().encode("utf-8")
        salt = hashlib.sha512(hostname).hexdigest()
        pw_hash = hashlib.sha512(
            str(salt + password).encode("utf-8")).hexdigest()
        self.config.set_value("WEB", "password", pw_hash)
        print("Password successfully saved.")

    def saveuser(self, username):
        """the function saves the username into the config file using the config class"""
        self.config.set_value("WEB", "username", username)
        print("Username successfully saved.")

    def ask_user(self):
        """the function asks the user for the username and password"""
        username = input("easywall Web Username: "******"easywall Web Password: ")
        self.savepasswd(password)
Ejemplo n.º 3
0
class TestLogin(unittest.TestCase):
    """
    TODO: Doku
    """
    def setUp(self):
        prepare_configuration()
        self.client = prepare_client()
        self.config = Config(CONFIG_PATH)

    def tearDown(self):
        restore_configuration()

    def test_login(self):
        """
        TODO: Doku
        """
        self.client.get('/login')

    def test_login_post(self):
        """
        TODO: Doku
        """
        self.log_in(self.client)

    def test_logout(self):
        """
        TODO: Doku
        """
        self.log_in(self.client)
        self.client.get('/logout', follow_redirects=True)

    def set_username_password(self):
        """
        TODO: Doku
        """
        self.config = Config(CONFIG_PATH)
        self.config.set_value("WEB", "username", "test")
        hostname = platform.node().encode("utf-8")
        salt = hashlib.sha512(hostname).hexdigest()
        pw_hash = hashlib.sha512(str(salt +
                                     "test").encode("utf-8")).hexdigest()
        self.config.set_value("WEB", "password", pw_hash)

    def log_in(self, client):
        """
        TODO: Doku
        """
        self.set_username_password()
        return client.post('/login',
                           data=dict(username="******", password="******"),
                           follow_redirects=True)
Ejemplo n.º 4
0
def prepare_configuration() -> None:
    """
    TODO: Doku
    """

    if file_exists(CONFIG_PATH):
        rename_file(CONFIG_PATH, CONFIG_BACKUP_PATH)

    content = """[LOG]
level = info
to_files = no
to_stdout = yes
filepath = log
filename = easywall-web.log

[WEB]
username = demo
password = xxx
bindip = 0.0.0.0
bindport = 12227
login_attempts = 10
login_bantime = 1800

[VERSION]
version = 0.0.0
sha = 12345
date = 2020-01-01T00:00:00Z
timestamp = 1234

[uwsgi]
https-socket = 0.0.0.0:12227,easywall.crt,easywall.key
processes = 5
threads = 2
callable = APP
master = false
wsgi-file = easywall_web/__main__.py
need-plugin = python3
"""

    create_file_if_not_exists(CONFIG_PATH)
    write_into_file(CONFIG_PATH, content)
    config = Config(CONFIG_PATH)
    config.set_value("VERSION", "timestamp", str(int(time())))
Ejemplo n.º 5
0
class Passwd(object):
    """the class contains the password generation and saving"""
    def __init__(self) -> None:
        """the init function creates the config variable and calls the user input"""
        self.config = Config(CONFIG_PATH)

        parser = argparse.ArgumentParser()
        parser.add_argument("--username", "-u", help="set username")
        parser.add_argument("--password", "-p", help="set password")
        args = parser.parse_args()

        if args.username and args.password:
            self.saveuser(args.username)
            self.savepasswd(args.password)
        else:
            self.ask_user()

    def savepasswd(self, password: str) -> None:
        """the function saves the password into the config file using the config class"""
        hostname = platform.node().encode("utf-8")
        salt = hashlib.sha512(hostname).hexdigest()
        pw_hash = hashlib.sha512(str(salt +
                                     password).encode("utf-8")).hexdigest()
        self.config.set_value("WEB", "password", pw_hash)
        print("Password successfully saved.")

    def saveuser(self, username: str) -> None:
        """the function saves the username into the config file using the config class"""
        self.config.set_value("WEB", "username", username)
        print("Username successfully saved.")

    def ask_user(self) -> None:
        """the function asks the user for the username and password"""
        username = input("easywall Web Username: "******"easywall Web Password: "******"easywall Web Password repeat: ")
        if password == password_repeat:
            self.savepasswd(password)
        else:
            print("password is not equal. password not saved!")
Ejemplo n.º 6
0
class TestConfig(unittest.TestCase):
    """
    this class contains all test functions for the config module
    """
    def setUp(self):
        content = """[TEST]
        teststring = string
        testboolean = true
        testint = 1
        testfloat = 1.1
        """
        create_file_if_not_exists("test.ini")
        write_into_file("test.ini", content)

        self.config = Config("test.ini")

    def tearDown(self):
        delete_file_if_exists("test.ini")

    def test_get_value_error(self):
        self.assertEqual(self.config.get_value("TEST", "notexistent"), "")

    def test_get_value_bool(self):
        self.assertEqual(self.config.get_value("TEST", "testboolean"), True)

    def test_get_value_int(self):
        self.assertEqual(self.config.get_value("TEST", "testint"), 1)

    def test_get_value_float(self):
        self.assertEqual(self.config.get_value("TEST", "testfloat"),
                         float(1.1))

    def test_get_sections(self):
        self.assertIn("TEST", self.config.get_sections())

    def test_set_value_success(self):
        self.assertEqual(self.config.set_value("TEST", "teststring", "erfolg"),
                         True)

    def test_set_value_fail_section(self):
        self.assertEqual(self.config.set_value("TEST2", "asd", "asd"), False)
Ejemplo n.º 7
0
class TestAcceptance(unittest.TestCase):
    """TODO: Doku."""
    def setUp(self) -> None:
        """TODO: Doku."""
        prepare_configuration()
        self.config = Config(CONFIG_PATH)
        self.acceptance = Acceptance(self.config)

    def tearDown(self) -> None:
        """TODO: Doku."""
        restore_configuration()

    def test_disabled(self) -> None:
        """TODO: Doku."""
        self.config = Config(CONFIG_PATH)
        self.config.set_value("ACCEPTANCE", "enabled", "no")
        self.acceptance = Acceptance(self.config)
        self.assertEqual(self.acceptance.status(), "disabled")

    def test_not_accepted(self) -> None:
        """TODO: Doku."""
        self.acceptance.start()
        self.acceptance.wait()
        self.assertEqual(self.acceptance.status(), "not accepted")

    def test_accepted(self) -> None:
        """TODO: Doku."""
        self.acceptance.start()
        self.acceptance.wait()
        write_into_file(self.acceptance.filename, "true")
        self.assertEqual(self.acceptance.status(), "accepted")

    def test_accepted_early(self) -> None:
        """TODO: Doku."""
        self.acceptance.start()
        write_into_file(self.acceptance.filename, "true")
        self.acceptance.wait()
        self.assertEqual(self.acceptance.status(), "accepted")
Ejemplo n.º 8
0
class Webutils(object):
    """Create a couple of shared functions used in the route functions."""
    def __init__(self) -> None:
        """TODO: Doku."""
        self.cfg = Config("config/web.ini")
        self.cfg_easywall = Config(CONFIG_PATH)
        self.cfg_log = Config(LOG_CONFIG_PATH)

    def check_login(self, request: Request) -> bool:
        """Check if the user/session is logged in."""
        if not session.get('logged_in'):
            return False
        if request.remote_addr != session.get('ip_address'):
            return False
        return True

    def check_first_run(self) -> bool:
        """Check if the webinterface is run for the first time."""
        username = self.cfg.get_value("WEB", "username")
        password = self.cfg.get_value("WEB", "password")
        if username == "" or password == "":
            return True
        return False

    # -------------------------
    # Payload Operations

    def get_default_payload(self,
                            title: str,
                            css: str = "easywall") -> DefaultPayload:
        """Create a object of information that are needed on every page."""
        payload = DefaultPayload()
        payload.year = datetime.today().year
        payload.title = title
        payload.customcss = css
        payload.machine = self.get_machine_infos()
        payload.latest_version = str(self.cfg.get_value("VERSION", "version"))
        payload.current_version = file_get_contents(".version")
        payload.commit_sha = str(self.cfg.get_value("VERSION", "sha"))
        payload.commit_date = self.get_commit_date(
            str(self.cfg.get_value("VERSION", "date")))
        payload.config_mismatch = self.get_config_version_mismatch("core")
        payload.web_config_mismatch = self.get_config_version_mismatch("web")
        return payload

    def get_machine_infos(self) -> dict:
        """Retrieve some information about the host and returns them as a list."""
        infos = {}
        infos["Machine"] = platform.machine()
        infos["Hostname"] = platform.node()
        infos["Platform"] = platform.platform()
        infos["Python Build"] = "".join(platform.python_build())
        infos["Python Compiler"] = platform.python_compiler()
        infos["Python Implementation"] = platform.python_implementation()
        infos["Python Version"] = platform.python_version()
        infos["Release"] = platform.release()
        infos["Libc Version"] = "".join(platform.libc_ver())
        return infos

    def get_config_version_mismatch(self, cfgtype: str) -> bool:
        """TODO: Doku."""
        if cfgtype == "core":
            cfg1 = Config("config/easywall.sample.ini")
            cfg2 = Config("config/easywall.ini")
        elif cfgtype == "web":
            cfg1 = Config("config/web.sample.ini")
            cfg2 = Config("config/web.ini")
        for section in cfg1.get_sections():
            if section not in cfg2.get_sections():
                return True
            for key in cfg1.get_keys(section):
                if key not in cfg2.get_keys(section):
                    return True
        return False

    # -------------------------
    # Update Info Operations

    def get_commit_date(self, datestring: str) -> str:
        """
        Compare a datetime with the current date.

        for comparing the datestring parameter is in UTC timezone
        """
        date1 = datetime.strptime(str(datestring), "%Y-%m-%dT%H:%M:%SZ")
        date1 = date1.replace(tzinfo=timezone.utc).astimezone(tz=None).replace(
            tzinfo=None)
        date2 = datetime.now()
        return time_duration_diff(date1, date2)

    def update_last_commit_infos(self) -> None:
        """
        Retrieve the last commit information after a specific waiting time.

        after retrieving the information they are saved into the config file
        """
        currtime = int(time.time())
        lasttime = int(self.cfg.get_value("VERSION", "timestamp"))
        waitseconds = 3600  # 60 minutes × 60 seconds
        if currtime > (lasttime + waitseconds):
            commit = self.get_latest_commit()
            self.cfg.set_value("VERSION", "version", self.get_latest_version())
            self.cfg.set_value("VERSION", "sha", commit["sha"])
            self.cfg.set_value("VERSION", "date",
                               commit["commit"]["author"]["date"])
            self.cfg.set_value("VERSION", "timestamp", str(currtime))

    def get_latest_commit(self) -> Any:
        """
        Retrieve the informations of the last commit from github as json.

        also converts the information into a python object
        for example the object contains the last commit date and the last commit sha
        This function should not be called very often, because GitHub has a rate limit implemented
        """
        url = "https://api.github.com/repos/jpylypiw/easywall/commits/master"
        req = urllib.request.Request(
            url,
            data=None,
            headers={'User-Agent': 'easywall by github.com/jpylypiw/easywall'})
        if req.get_full_url().lower().startswith("https"):
            response = urllib.request.urlopen(req)
        else:
            raise ValueError from None
        return json.loads(response.read().decode('utf-8'))

    def get_latest_version(self) -> str:
        """Retrieve the latest version from github and returns the version string."""
        url = "https://raw.githubusercontent.com/jpylypiw/easywall/master/.version"
        req = urllib.request.Request(
            url,
            data=None,
            headers={'User-Agent': 'easywall by github.com/jpylypiw/easywall'})
        if req.get_full_url().lower().startswith("https"):
            response = urllib.request.urlopen(req)
        else:
            raise ValueError from None
        data = response.read()
        return str(data.decode('utf-8'))

    # -------------------------
    # Acceptance Operations

    def get_last_accept_time(self) -> str:
        """
        Retrieve the modify time of the acceptance file.

        also compares the time to the current time
        """
        timestamp = str(self.cfg_easywall.get_value("ACCEPTANCE", "timestamp"))
        if timestamp == "":
            return "never"
        timestamp_datetime = datetime.strptime(timestamp,
                                               '%Y-%m-%d %H:%M:%S.%f')
        now = datetime.now()
        return time_duration_diff(timestamp_datetime, now)

    def get_acceptance_status(self) -> str:
        """Get the status of the current acceptance."""
        filepath = ".acceptance_status"
        if file_exists(filepath):
            return file_get_contents(filepath)
        return ""
Ejemplo n.º 9
0
class Webutils(object):
    """the class is called in the route modules and contains non route-specific functions"""

    def __init__(self):
        self.cfg = Config("config/web.ini")

    def check_login(self):
        """the function checks if the user/session is logged in"""
        if not session.get('logged_in'):
            return False
        return True

    # -------------------------
    # Payload Operations

    def get_default_payload(self, title, css="easywall"):
        """the function creates a object of information that are needed on every page"""
        payload = DefaultPayload()
        payload.year = datetime.today().year
        payload.title = title
        payload.customcss = css
        payload.machine = self.get_machine_infos()
        payload.latest_version = self.cfg.get_value("VERSION", "version")
        payload.current_version = file_get_contents("{}/../.version".format(get_abs_path_of_filepath(__file__)))
        payload.commit_sha = self.cfg.get_value("VERSION", "sha")
        payload.commit_date = self.get_commit_date(self.cfg.get_value("VERSION", "date"))
        return payload

    def get_machine_infos(self):
        """the function retrieves some information about the host and returns them as a list"""
        infos = {}
        infos["Machine"] = platform.machine()
        infos["Hostname"] = platform.node()
        infos["Platform"] = platform.platform()
        infos["Python Build"] = platform.python_build()
        infos["Python Compiler"] = platform.python_compiler()
        infos["Python Implementation"] = platform.python_implementation()
        infos["Python Version"] = platform.python_version()
        infos["Release"] = platform.release()
        infos["Libc Version"] = platform.libc_ver()
        return infos

    # -------------------------
    # Update Info Operations

    def get_commit_date(self, datestring):
        """
        the function compares a datetime with the current date
        for comparing the datestring parameter is in UTC timezone
        """
        date1 = datetime.strptime(str(datestring), "%Y-%m-%dT%H:%M:%SZ")
        date1 = date1.replace(
            tzinfo=timezone.utc).astimezone(
                tz=None).replace(
                    tzinfo=None)
        date2 = datetime.now()
        return time_duration_diff(date1, date2)

    def update_last_commit_infos(self):
        """
        the function retrieves the last commit information after a specific waiting time
        after retrieving the information they are saved into the config file
        """
        currtime = int(time.time())
        lasttime = int(self.cfg.get_value("VERSION", "timestamp"))
        waitseconds = 3600  # 60 minutes × 60 seconds
        if currtime > (lasttime + waitseconds):
            commit = self.get_latest_commit()
            self.cfg.set_value("VERSION", "version", self.get_latest_version())
            self.cfg.set_value("VERSION", "sha", commit["sha"])
            self.cfg.set_value("VERSION", "date", commit["commit"]["author"]["date"])
            self.cfg.set_value("VERSION", "timestamp", currtime)

    def get_latest_commit(self):
        """
        retrieves the informations of the last commit from github as json
        and converts the information into a python object
        for example the object contains the last commit date and the last commit sha
        This function should not be called very often, because GitHub has a rate limit implemented
        """
        url = "https://api.github.com/repos/jpylypiw/easywall-web/commits/master"
        req = urllib.request.Request(
            url,
            data=None,
            headers={
                'User-Agent': 'easywall by github.com/jpylypiw/easywall-web'
            }
        )
        response = urllib.request.urlopen(req)
        return json.loads(response.read().decode('utf-8'))

    def get_latest_version(self):
        """
        the function retrieves the latest version from github and returns the version string
        """
        url = "https://raw.githubusercontent.com/jpylypiw/easywall-web/master/.version"
        req = urllib.request.Request(
            url,
            data=None,
            headers={
                'User-Agent': 'easywall by github.com/jpylypiw/easywall-web'
            }
        )
        response = urllib.request.urlopen(req)
        data = response.read()
        return data.decode('utf-8')

    # -------------------------
    # Rule Operations

    def get_rule_status(self, ruletype):
        """
        the function checks if a custom / temporary rulefile exists
        and returns "custom" when a temporary rulefile exists or "production" when no file exists
        """
        filepath = self.get_rule_file_path(ruletype, True)
        if not os.path.exists(filepath):
            filepath = self.get_rule_file_path(ruletype)
            if not os.path.exists(filepath):
                return "error"
            return "production"
        return "custom"

    def get_rule_file_path(self, ruletype, tmp=False):
        """
        the function reads the configuration and returns the relative
        or absolute path to the rulefile for the ruletype
        """
        filename = self.cfg.get_value("RULES", ruletype)
        if tmp:
            filepath = self.cfg.get_value("WEB", "rules_tmp_path")
        else:
            filepath = self.cfg.get_value("RULES", "filepath")
            # workaround because the easywall dir is one dir up - this is not pretty
            if filepath.startswith("."):
                filepath = "../" + filepath
        create_folder_if_not_exists(filepath)
        return filepath + "/" + filename

    def get_rule_list(self, ruletype):
        """
        the function reads a file into the ram and returns a list of all rows in a list
        for example you get all the ip addresses of the blacklist in a array
        """
        rule_list = []

        status = self.get_rule_status(ruletype)
        filepath = self.get_rule_file_path(ruletype)
        if status == "custom":
            filepath = self.get_rule_file_path(ruletype, True)

        with open(filepath, 'r') as rulesfile:
            for rule in rulesfile.read().split('\n'):
                if rule.strip() != "":
                    rule_list.append(rule)
        return rule_list

    def save_rule_list(self, ruletype, rulelist, to_production=False):
        """
        the function writes a list of strings into a rulesfile
        for example it saves the blacklist rules into the blacklist temporary rulesfile
        """
        filepath = self.get_rule_file_path(ruletype, True)
        state = self.get_rule_status(ruletype)
        if to_production:
            filepath = self.get_rule_file_path(ruletype)
        try:
            rulelist = list(filter(None, rulelist))
            if not to_production or to_production and state == "custom":
                with open(filepath, mode='wt', encoding='utf-8') as rulesfile:
                    rulesfile.write('\n'.join(rulelist))
        except Exception as exc:
            print("{}".format(exc))
            return False
        return True

    # -------------------------
    # Acceptance Operations

    def apply_rule_list(self, ruletype):
        """
        the function copys the rulefile from the temporary path to the permanent path
        this is used to copy the rules from web to easywall folder
        """
        rule_list = self.get_rule_list(ruletype)
        self.save_rule_list(ruletype, rule_list, True)

    def get_last_accept_time(self):
        """
        the function retrieves the modify time of the acceptance file
        and compares the time to the current time
        """
        filepath = "../" + self.cfg.get_value("ACCEPTANCE", "filename")
        if os.path.exists(filepath):
            mtime = os.path.getmtime(filepath)
            mtime = datetime.utcfromtimestamp(mtime)
            mtime = mtime.replace(
                tzinfo=timezone.utc).astimezone(
                    tz=None).replace(
                        tzinfo=None)
            now = datetime.now()
            return time_duration_diff(mtime, now)
        else:
            return "never"

    def check_acceptance_running(self):
        """
        the function checks if there is a running file.
        """
        filepath = "../.running"
        if os.path.exists(filepath):
            return True
        return False
Ejemplo n.º 10
0
class TestConfig(unittest.TestCase):
    """
    TODO: Doku
    """

    def setUp(self) -> None:
        content = """[TEST]
        teststring = string
        testboolean = true
        testint = 1
        testfloat = 1.1
        """
        create_file_if_not_exists("test.ini")
        write_into_file("test.ini", content)

        self.config = Config("test.ini")

    def tearDown(self) -> None:
        delete_file_if_exists("test.ini")

    def test_constructor_file_not_found(self) -> None:
        """
        TODO: Doku
        """
        with self.assertRaises(FileNotFoundError):
            Config("test2.ini")

    def test_constructor_file_not_read(self) -> None:
        """
        TODO: Doku
        """
        create_file_if_not_exists("test.ini")
        content = """[DEFAULT]
        goodcontent = test
        badcontent
        """
        write_into_file("test.ini", content)
        with self.assertRaises(ParsingError):
            Config("test.ini")

    def test_get_value_error(self) -> None:
        """
        TODO: Doku
        """
        self.assertEqual(self.config.get_value("TEST", "notexistent"), "")

    def test_get_value_bool(self) -> None:
        """
        TODO: Doku
        """
        self.assertEqual(self.config.get_value("TEST", "testboolean"), True)

    def test_get_value_int(self) -> None:
        """
        TODO: Doku
        """
        self.assertEqual(self.config.get_value("TEST", "testint"), 1)

    def test_get_value_float(self) -> None:
        """
        TODO: Doku
        """
        self.assertEqual(self.config.get_value(
            "TEST", "testfloat"), float(1.1))

    def test_get_sections(self) -> None:
        """
        TODO: Doku
        """
        self.assertIn("TEST", self.config.get_sections())

    def test_set_value_success(self) -> None:
        """
        TODO: Doku
        """
        self.assertEqual(self.config.set_value(
            "TEST", "teststring", "erfolg"), True)

    def test_set_value_fail_section(self) -> None:
        """
        TODO: Doku
        """
        self.assertEqual(self.config.set_value("TEST2", "asd", "asd"), False)
Ejemplo n.º 11
0
def prepare_configuration() -> None:
    """TODO: Doku."""
    if file_exists(EASYWALL_CONFIG_PATH):
        rename_file(EASYWALL_CONFIG_PATH, EASYWALL_CONFIG_BACKUP_PATH)
    if file_exists(WEB_CONFIG_PATH):
        rename_file(WEB_CONFIG_PATH, WEB_CONFIG_BACKUP_PATH)
    if file_exists(LOG_CONFIG_PATH):
        rename_file(LOG_CONFIG_PATH, LOG_CONFIG_BACKUP_PATH)

    content = """[IPTABLES]
log_blocked_connections = yes
log_blocked_connections_log_limit = 60
log_blacklist_connections = yes
log_blacklist_connections_log_limit = 60
drop_broadcast_packets = yes
drop_multicast_packets = yes
drop_anycast_packets = yes
ssh_brute_force_prevention = yes
ssh_brute_force_prevention_log = yes
ssh_brute_force_prevention_connection_limit = 5
ssh_brute_force_prevention_log_limit = 60
icmp_flood_prevention = yes
icmp_flood_prevention_log = yes
icmp_flood_prevention_connection_limit = 5
icmp_flood_prevention_log_limit = 60
drop_invalid_packets = yes
drop_invalid_packets_log = yes
drop_invalid_packets_log_limit = 60
port_scan_prevention = yes
port_scan_prevention_log = yes
port_scan_prevention_log_limit = 60

[IPV6]
enabled = yes
icmp_allow_router_advertisement = yes
icmp_allow_neighbor_advertisement = yes

[ACCEPTANCE]
enabled = yes
duration = 1
timestamp =

[EXEC]
iptables = /sbin/iptables
ip6tables = /sbin/ip6tables
iptables-save = /sbin/iptables-save
ip6tables-save = /sbin/ip6tables-save
iptables-restore = /sbin/iptables-restore
ip6tables-restore = /sbin/ip6tables-restore
"""

    create_file_if_not_exists(EASYWALL_CONFIG_PATH)
    write_into_file(EASYWALL_CONFIG_PATH, content)

    content = """[WEB]
username = demo
password = xxx
bindip = 0.0.0.0
bindport = 12227
login_attempts = 100
login_bantime = 1800

[VERSION]
version = 0.0.0
sha = 12345
date = 2020-01-01T00:00:00Z
timestamp = 1234

[uwsgi]
ssl-option = 268435456
https-socket = 0.0.0.0:12227,ssl/easywall.crt,ssl/easywall.key,HIGH
processes = 5
threads = 2
callable = APP
master = yes
die-on-term = yes
wsgi-file = easywall/web/__main__.py
need-plugin = python3
buffer-size = 16384
"""

    create_file_if_not_exists(WEB_CONFIG_PATH)
    write_into_file(WEB_CONFIG_PATH, content)
    config = Config(WEB_CONFIG_PATH)
    config.set_value("VERSION", "timestamp", str(int(time())))

    content = """[LOG]
level = info
to_files = no
to_stdout = yes
filepath = /var/log
filename = easywall.log
"""

    create_file_if_not_exists(LOG_CONFIG_PATH)
    write_into_file(LOG_CONFIG_PATH, content)
Ejemplo n.º 12
0
class Webutils(object):
    """the class is called in the route modules and contains non route-specific functions"""
    def __init__(self):
        self.cfg = Config("config/web.ini")
        self.cfg_easywall = Config(CONFIG_PATH)

    def check_login(self):
        """the function checks if the user/session is logged in"""
        if not session.get('logged_in'):
            return False
        return True

    # -------------------------
    # Payload Operations

    def get_default_payload(self, title, css="easywall"):
        """the function creates a object of information that are needed on every page"""
        payload = DefaultPayload()
        payload.year = datetime.today().year
        payload.title = title
        payload.customcss = css
        payload.machine = self.get_machine_infos()
        payload.latest_version = self.cfg.get_value("VERSION", "version")
        payload.current_version = file_get_contents(".version")
        payload.commit_sha = self.cfg.get_value("VERSION", "sha")
        payload.commit_date = self.get_commit_date(
            self.cfg.get_value("VERSION", "date"))
        return payload

    def get_machine_infos(self):
        """the function retrieves some information about the host and returns them as a list"""
        infos = {}
        infos["Machine"] = platform.machine()
        infos["Hostname"] = platform.node()
        infos["Platform"] = platform.platform()
        infos["Python Build"] = platform.python_build()
        infos["Python Compiler"] = platform.python_compiler()
        infos["Python Implementation"] = platform.python_implementation()
        infos["Python Version"] = platform.python_version()
        infos["Release"] = platform.release()
        infos["Libc Version"] = platform.libc_ver()
        return infos

    # -------------------------
    # Update Info Operations

    def get_commit_date(self, datestring):
        """
        the function compares a datetime with the current date
        for comparing the datestring parameter is in UTC timezone
        """
        date1 = datetime.strptime(str(datestring), "%Y-%m-%dT%H:%M:%SZ")
        date1 = date1.replace(tzinfo=timezone.utc).astimezone(tz=None).replace(
            tzinfo=None)
        date2 = datetime.now()
        return time_duration_diff(date1, date2)

    def update_last_commit_infos(self):
        """
        the function retrieves the last commit information after a specific waiting time
        after retrieving the information they are saved into the config file
        """
        currtime = int(time.time())
        lasttime = self.cfg.get_value("VERSION", "timestamp")
        waitseconds = 3600  # 60 minutes × 60 seconds
        if currtime > (lasttime + waitseconds):
            commit = self.get_latest_commit()
            self.cfg.set_value("VERSION", "version", self.get_latest_version())
            self.cfg.set_value("VERSION", "sha", commit["sha"])
            self.cfg.set_value("VERSION", "date",
                               commit["commit"]["author"]["date"])
            self.cfg.set_value("VERSION", "timestamp", str(currtime))

    def get_latest_commit(self):
        """
        retrieves the informations of the last commit from github as json
        and converts the information into a python object
        for example the object contains the last commit date and the last commit sha
        This function should not be called very often, because GitHub has a rate limit implemented
        """
        url = "https://api.github.com/repos/jpylypiw/easywall/commits/master"
        req = urllib.request.Request(
            url,
            data=None,
            headers={'User-Agent': 'easywall by github.com/jpylypiw/easywall'})
        response = urllib.request.urlopen(req)
        return json.loads(response.read().decode('utf-8'))

    def get_latest_version(self) -> str:
        """
        the function retrieves the latest version from github and returns the version string
        """
        url = "https://raw.githubusercontent.com/jpylypiw/easywall/master/.version"
        req = urllib.request.Request(
            url,
            data=None,
            headers={'User-Agent': 'easywall by github.com/jpylypiw/easywall'})
        response = urllib.request.urlopen(req)
        data = response.read()
        return data.decode('utf-8')

    # -------------------------
    # Acceptance Operations

    def get_last_accept_time(self):
        """
        the function retrieves the modify time of the acceptance file
        and compares the time to the current time
        """
        timestamp = self.cfg_easywall.get_value("ACCEPTANCE", "timestamp")
        if timestamp == "":
            return "never"
        timestamp = datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S.%f')
        now = datetime.now()
        return time_duration_diff(timestamp, now)

    def get_acceptance_status(self):
        """
        get the status of the current acceptance
        """
        filepath = ".acceptance_status"
        if file_exists(filepath):
            return file_get_contents(filepath)
        return ""