From f34227fa6e3d3ac4d2c76bebb7986ec775a47085 Mon Sep 17 00:00:00 2001 From: NaruX Date: Sun, 11 Mar 2018 15:28:44 +0100 Subject: [PATCH] IpAclManager erweitert picontrolserver auf IpAclManager umgeschrieben --- doc/helper.html | 65 ++++++++++++---------------------- doc/picontrolserver.html | 2 +- doc/revpipyload.html | 2 +- doc/xrpcserver.html | 4 +-- eric-revpipyload.api | 13 ++++--- revpipyload/helper.py | 61 ++++++++++++++++--------------- revpipyload/picontrolserver.py | 13 ++----- revpipyload/revpipyload.py | 42 ++++++++++------------ revpipyload/xrpcserver.py | 21 +++++++---- 9 files changed, 99 insertions(+), 124 deletions(-) diff --git a/doc/helper.html b/doc/helper.html index ffb07cc..5a3e665 100644 --- a/doc/helper.html +++ b/doc/helper.html @@ -26,9 +26,6 @@ Classes Functions - - - @@ -51,7 +48,7 @@ None

Class Attributes

_ipmatchPrueft IP gegen ACL List und gibt ACL aus.
_setuprt Konfiguriert Programm fuer den RT-Scheduler.
- +
acl
acl
regex_acl

Class Methods

@@ -68,14 +65,17 @@ Methods __get_acl Getter fuer den rohen ACL-String. -__refullmatch -re.fullmatch wegen alter python version aus wheezy nachgebaut. +__get_regex_acl +Gibt formatierten RegEx-String zurueck. __set_acl Uebernimmt neue ACL-Liste fuer die Ausertung der Level. get_acllevel Prueft IP gegen ACL List und gibt ACL-Wert aus. + +valid_acl_string +Prueft ob ein ACL-String gueltig ist.

@@ -86,7 +86,7 @@ Static Methods

IpAclManager (Constructor)

-IpAclManager(acl=None, minlevel=0, maxlevel=1) +IpAclManager(acl=None, minlevel=0, maxlevel=0)

Init IpAclManager class.

@@ -101,26 +101,14 @@ IpAclManager.__get_acl

Getter fuer den rohen ACL-String. return ACLs als -

+

-IpAclManager.__refullmatch

-__refullmatch(regex, string) +IpAclManager.__get_regex_acl +__get_regex_acl()

-re.fullmatch wegen alter python version aus wheezy nachgebaut. -

-
regex
-
-RegEx Statement -
string
-
-Zeichenfolge gegen die getestet wird -
-
-
Returns:
-
-True, wenn komplett passt sonst False -
-
+Gibt formatierten RegEx-String zurueck. + return RegEx Code als +

IpAclManager.__set_acl

__set_acl(value) @@ -145,28 +133,19 @@ zum pruefen
Returns:
-int() ACL Wert oder -1 wenn nicht gefunden + ACL Wert oder -1 wenn nicht gefunden
-
-
Up
-

- -

_ipmatch

-_ipmatch(ipaddress, dict_acl) + +

+IpAclManager.valid_acl_string

+valid_acl_string(str_acl)

-Prueft IP gegen ACL List und gibt ACL aus. +Prueft ob ein ACL-String gueltig ist.

-
ipaddress
+
str_acl
-zum pruefen -
dict_acl
-
-ACL Dict gegen die IP zu pruefen ist -
-
-
Returns:
-
-int() ACL Wert oder -1 wenn nicht gefunden + zum ueberpruefen + return ACL Level als
Up
diff --git a/doc/picontrolserver.html b/doc/picontrolserver.html index d72e85c..1cef53d 100644 --- a/doc/picontrolserver.html +++ b/doc/picontrolserver.html @@ -81,7 +81,7 @@ Static Methods

RevPiSlave (Constructor)

-RevPiSlave(acl, port=55234) +RevPiSlave(ipacl, port=55234)

Instantiiert RevPiSlave-Klasse.

diff --git a/doc/revpipyload.html b/doc/revpipyload.html index d7a7855..33187e1 100644 --- a/doc/revpipyload.html +++ b/doc/revpipyload.html @@ -32,7 +32,7 @@ begrenzt werden!

Global Attributes

- +
pyloadversion
re_ipacl
pyloadversion

Classes

diff --git a/doc/xrpcserver.html b/doc/xrpcserver.html index cfabcee..ed0f8c0 100644 --- a/doc/xrpcserver.html +++ b/doc/xrpcserver.html @@ -87,7 +87,7 @@ SimpleXMLRPCServer

Class Attributes

- +
aclmgr
None

Class Methods

@@ -119,7 +119,7 @@ Static Methods

SaveXMLRPCServer (Constructor)

-SaveXMLRPCServer(addr, logRequests=True, allow_none=False, use_builtin_types=False, acl="") +SaveXMLRPCServer(addr, logRequests=True, allow_none=False, use_builtin_types=False, ipacl=IpAclManager())

Init SaveXMLRPCServer class.

diff --git a/eric-revpipyload.api b/eric-revpipyload.api index 836c158..382abc0 100644 --- a/eric-revpipyload.api +++ b/eric-revpipyload.api @@ -1,10 +1,11 @@ helper.IpAclManager.__get_acl?6() -helper.IpAclManager.__refullmatch?6(regex, string) +helper.IpAclManager.__get_regex_acl?6() helper.IpAclManager.__set_acl?6(value) helper.IpAclManager.acl?7 helper.IpAclManager.get_acllevel?4(ipaddress) -helper.IpAclManager?1(acl=None, minlevel=0, maxlevel=1) -helper._ipmatch?5(ipaddress, dict_acl) +helper.IpAclManager.regex_acl?7 +helper.IpAclManager.valid_acl_string?4(str_acl) +helper.IpAclManager?1(acl=None, minlevel=0, maxlevel=0) helper._setuprt?5(pid, evt_exit) helper._zeroprocimg?5() helper.refullmatch?4(regex, string) @@ -22,7 +23,7 @@ logsystem.PipeLogwriter?1(logfilename) picontrolserver.RevPiSlave.newlogfile?4() picontrolserver.RevPiSlave.run?4() picontrolserver.RevPiSlave.stop?4() -picontrolserver.RevPiSlave?1(acl, port=55234) +picontrolserver.RevPiSlave?1(ipacl, port=55234) picontrolserver.RevPiSlaveDev.run?4() picontrolserver.RevPiSlaveDev.stop?4() picontrolserver.RevPiSlaveDev?1(devcon, acl) @@ -83,10 +84,8 @@ revpipyload.RevPiPyLoad.xml_setconfig?4(dc, loadnow=False) revpipyload.RevPiPyLoad.xml_setpictoryrsc?4(filebytes, reset=False) revpipyload.RevPiPyLoad?1() revpipyload.pyloadversion?7 -revpipyload.re_ipacl?7 xrpcserver.SaveXMLRPCRequestHandler.parse_request?4() -xrpcserver.SaveXMLRPCServer.aclmgr?7 xrpcserver.SaveXMLRPCServer.isAlive?4() xrpcserver.SaveXMLRPCServer.start?4() xrpcserver.SaveXMLRPCServer.stop?4() -xrpcserver.SaveXMLRPCServer?1(addr, logRequests=True, allow_none=False, use_builtin_types=False, acl="") +xrpcserver.SaveXMLRPCServer?1(addr, logRequests=True, allow_none=False, use_builtin_types=False, ipacl=IpAclManager()) diff --git a/revpipyload/helper.py b/revpipyload/helper.py index 1534bd6..870bc96 100644 --- a/revpipyload/helper.py +++ b/revpipyload/helper.py @@ -16,13 +16,16 @@ class IpAclManager(): """Verwaltung fuer IP Adressen und deren ACL Level.""" - def __init__(self, acl=None, minlevel=0, maxlevel=1): + def __init__(self, acl=None, minlevel=0, maxlevel=0): """Init IpAclManager class. @param acl ACL Liste fuer Berechtigungen als """ - if minlevel >= maxlevel: - raise ValueError("minlevel is smaller or equal than maxlevel") + if minlevel > maxlevel: + raise ValueError("minlevel is smaller than maxlevel") + if minlevel < 0: + raise ValueError("minlevel must be 0 or more") self.__dict_acl = {} + self.__dict_ips = {} self.__rawacl = "" self.__re_ipacl = "(([\\d\\*]{1,3}\\.){3}[\\d\\*]{1,3},[" \ + str(minlevel) + "-" + str(maxlevel) + "] ?)*" @@ -36,16 +39,10 @@ class IpAclManager(): return ACLs als """ return self.__rawacl - def __refullmatch(self, regex, string): - """re.fullmatch wegen alter python version aus wheezy nachgebaut. - - @param regex RegEx Statement - @param string Zeichenfolge gegen die getestet wird - @return True, wenn komplett passt sonst False - - """ - m = rematch(regex, string) - return m is not None and m.end() == len(string) + def __get_regex_acl(self): + """Gibt formatierten RegEx-String zurueck. + return RegEx Code als """ + return self.__re_ipacl def __set_acl(self, value): """Uebernimmt neue ACL-Liste fuer die Ausertung der Level. @@ -53,11 +50,12 @@ class IpAclManager(): if type(value) != str: raise ValueError("parameter acl must be ") - if not self.__refullmatch(self.__re_ipacl, value): + if not self.valid_acl_string(value): raise ValueError("acl format ist not okay - 1.2.3.4,0 5.6.7.8,1") # Klassenwerte übernehmen self.__dict_acl = {} + self.__dict_ips = {} self.__rawacl = value # Liste neu füllen mit regex Strings @@ -69,28 +67,29 @@ class IpAclManager(): def get_acllevel(self, ipaddress): """Prueft IP gegen ACL List und gibt ACL-Wert aus. @param ipaddress zum pruefen - @return int() ACL Wert oder -1 wenn nicht gefunden""" + @return ACL Wert oder -1 wenn nicht gefunden""" + # Bei bereits aufgelösten IPs direkt ACL auswerten + if ipaddress in self.__dict_ips: + return self.__dict_ips[ipaddress] + for aclip in sorted(self.__dict_acl, reverse=True): - if self.__refullmatch(aclip, ipaddress): + if refullmatch(aclip, ipaddress): + # IP und Level merken + self.__dict_ips[ipaddress] = self.__dict_acl[aclip] + + # Level zurückgeben return self.__dict_acl[aclip] + return -1 + def valid_acl_string(self, str_acl): + """Prueft ob ein ACL-String gueltig ist. + @param str_acl zum ueberpruefen + return ACL Level als """ + return refullmatch(self.__re_ipacl, str_acl) + acl = property(__get_acl, __set_acl) - - -def _ipmatch(ipaddress, dict_acl): - """Prueft IP gegen ACL List und gibt ACL aus. - - @param ipaddress zum pruefen - @param dict_acl ACL Dict gegen die IP zu pruefen ist - @return int() ACL Wert oder -1 wenn nicht gefunden - - """ - for aclip in sorted(dict_acl, reverse=True): - regex = aclip.replace(".", "\\.").replace("*", "\\d{1,3}") - if refullmatch(regex, ipaddress): - return dict_acl[aclip] - return -1 + regex_acl = property(__get_regex_acl) def _setuprt(pid, evt_exit): diff --git a/revpipyload/picontrolserver.py b/revpipyload/picontrolserver.py index 5ac32fa..8be9c55 100644 --- a/revpipyload/picontrolserver.py +++ b/revpipyload/picontrolserver.py @@ -8,7 +8,6 @@ """Modul fuer die Verwaltung der PLC-Slave Funktionen.""" import proginit import socket -from helper import _ipmatch from threading import Event, Thread from timeit import default_timer @@ -24,11 +23,12 @@ class RevPiSlave(Thread): """ - def __init__(self, acl, port=55234): + def __init__(self, ipacl, port=55234): """Instantiiert RevPiSlave-Klasse. @param acl Stringliste mit Leerstellen getrennt @param port Listen Port fuer plc Slaveserver""" super().__init__() + self.__ipacl = ipacl self._evt_exit = Event() self.exitcode = None self._port = port @@ -37,13 +37,6 @@ class RevPiSlave(Thread): self.zeroonerror = False self.zeroonexit = False - # ACLs aufbereiten - self.dict_acl = {} - for host in acl.split(): - aclsplit = host.split(",") - self.dict_acl[aclsplit[0]] = \ - 0 if len(aclsplit) == 1 else int(aclsplit[1]) - def newlogfile(self): """Konfiguriert die FileHandler auf neue Logdatei.""" pass @@ -78,7 +71,7 @@ class RevPiSlave(Thread): continue # ACL prüfen - aclstatus = _ipmatch(tup_sock[1][0], self.dict_acl) + aclstatus = self.__ipacl.get_acllevel(tup_sock[1][0]) if aclstatus == -1: tup_sock[0].close() proginit.logger.warning( diff --git a/revpipyload/revpipyload.py b/revpipyload/revpipyload.py index 324192f..75839b7 100755 --- a/revpipyload/revpipyload.py +++ b/revpipyload/revpipyload.py @@ -40,7 +40,7 @@ import signal import tarfile import zipfile from configparser import ConfigParser -from helper import refullmatch +from helper import refullmatch, IpAclManager from json import loads as jloads from shutil import rmtree from tempfile import mkstemp @@ -50,7 +50,6 @@ from xmlrpc.client import Binary from xrpcserver import SaveXMLRPCServer pyloadversion = "0.6.0" -re_ipacl = "(([\\d\\*]{1,3}\\.){3}[\\d\\*]{1,3},[0-1] ?)*" class RevPiPyLoad(): @@ -120,36 +119,33 @@ class RevPiPyLoad(): self.globalconfig["DEFAULT"].get("plcarguments", "") self.plcworkdir = \ self.globalconfig["DEFAULT"].get("plcworkdir", ".") - self.plcslave = \ - int(self.globalconfig["DEFAULT"].get("plcslave", 0)) # PLC Slave ACL laden und prüfen - plcslaveacl = \ - self.globalconfig["DEFAULT"].get("plcslaveacl", "") - if len(plcslaveacl) > 0 and not refullmatch(re_ipacl, plcslaveacl): - self.plcslaveacl = "" + self.plcslave = \ + int(self.globalconfig["DEFAULT"].get("plcslave", 0)) + self.plcslaveacl = IpAclManager(minlevel=0, maxlevel=1) + str_acl = self.globalconfig["DEFAULT"].get("plcslaveacl", "") + if not self.plcslaveacl.valid_acl_string(str_acl): proginit.logger.warning("can not load plcslaveacl - wrong format") else: - self.plcslaveacl = plcslaveacl - + self.plcslaveacl.acl = str_acl self.plcslaveport = \ int(self.globalconfig["DEFAULT"].get("plcslaveport", 55234)) + self.pythonver = \ int(self.globalconfig["DEFAULT"].get("pythonversion", 3)) self.rtlevel = \ int(self.globalconfig["DEFAULT"].get("rtlevel", 0)) - self.xmlrpc = \ - int(self.globalconfig["DEFAULT"].get("xmlrpc", 0)) # XML ACL laden und prüfen - # TODO: xmlrpcacl auswerten - xmlrpcacl = \ - self.globalconfig["DEFAULT"].get("xmlrpcacl", "") - if len(xmlrpcacl) > 0 and not refullmatch(re_ipacl, xmlrpcacl): - self.xmlrpcacl = "" + self.xmlrpc = \ + int(self.globalconfig["DEFAULT"].get("xmlrpc", 0)) + self.xmlrpcacl = IpAclManager(minlevel=0, maxlevel=3) + str_acl = self.globalconfig["DEFAULT"].get("xmlrpcacl", "") + if not self.xmlrpcacl.valid_acl_string(str_acl): proginit.logger.warning("can not load xmlrpcacl - wrong format") else: - self.xmlrpcacl = xmlrpcacl + self.xmlrpcacl.acl = str_acl self.zeroonerror = \ int(self.globalconfig["DEFAULT"].get("zeroonerror", 1)) @@ -177,7 +173,7 @@ class RevPiPyLoad(): ), logRequests=False, allow_none=True, - acl=self.xmlrpcacl + ipacl=self.xmlrpcacl ) self.xsrv.register_introspection_functions() self.xsrv.register_multicall_functions() @@ -466,12 +462,12 @@ class RevPiPyLoad(): dc["plcprogram"] = self.plcprog dc["plcarguments"] = self.plcarguments dc["plcslave"] = self.plcslave - dc["plcslaveacl"] = self.plcslaveacl + dc["plcslaveacl"] = self.plcslaveacl.acl dc["plcslaveport"] = self.plcslaveport dc["pythonversion"] = self.pythonver dc["rtlevel"] = self.rtlevel dc["xmlrpc"] = self.xmlrpc - dc["xmlrpcacl"] = self.xmlrpcacl + dc["xmlrpcacl"] = self.xmlrpcacl.acl dc["zeroonerror"] = self.zeroonerror dc["zeroonexit"] = self.zeroonexit return dc @@ -640,12 +636,12 @@ class RevPiPyLoad(): "plcprogram": ".+", "plcarguments": ".*", "plcslave": "[01]", - "plcslaveacl": re_ipacl, + "plcslaveacl": self.plcslaveacl.regex_acl, "plcslaveport": "[0-9]{,5}", "pythonversion": "[23]", "rtlevel": "[0-1]", "xmlrpc": "[0-3]", - "xmlrpcacl": re_ipacl, + "xmlrpcacl": self.xmlrpcacl.regex_acl, "zeroonerror": "[01]", "zeroonexit": "[01]" } diff --git a/revpipyload/xrpcserver.py b/revpipyload/xrpcserver.py index cb03309..f6f6a0d 100644 --- a/revpipyload/xrpcserver.py +++ b/revpipyload/xrpcserver.py @@ -6,6 +6,7 @@ # (c) Sven Sager, License: LGPLv3 # """XML-RPC Server anpassungen fuer Absicherung.""" +import proginit from helper import IpAclManager from concurrent import futures from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler @@ -15,14 +16,11 @@ class SaveXMLRPCServer(SimpleXMLRPCServer): """Erstellt einen erweiterten XMLRPCServer.""" - aclmgr = IpAclManager() - def __init__( self, addr, logRequests=True, allow_none=False, - use_builtin_types=False, acl=""): + use_builtin_types=False, ipacl=IpAclManager()): """Init SaveXMLRPCServer class.""" - - SaveXMLRPCServer.aclmgr.acl = acl + proginit.logger.debug("enter SaveXMLRPCServer.__init__()") # Vererbte Klasse instantiieren super().__init__( @@ -36,9 +34,12 @@ class SaveXMLRPCServer(SimpleXMLRPCServer): ) # Klassenvariablen + self.aclmgr = ipacl self.tpe = futures.ThreadPoolExecutor(max_workers=1) self.fut = None + proginit.logger.debug("leave SaveXMLRPCServer.__init__()") + def isAlive(self): """Prueft ob der XML RPC Server laeuft. @return True, wenn Server noch laeuft""" @@ -46,6 +47,8 @@ class SaveXMLRPCServer(SimpleXMLRPCServer): def start(self): """Startet den XML-RPC Server.""" + proginit.logger.debug("enter SaveXMLRPCServer.start()") + if self.fut is None: self.server_bind() self.server_activate() @@ -53,8 +56,12 @@ class SaveXMLRPCServer(SimpleXMLRPCServer): else: raise RuntimeError("savexmlrpcservers can only be started once") + proginit.logger.debug("leave SaveXMLRPCServer.start()") + def stop(self): """Stoppt den XML-RPC Server.""" + proginit.logger.debug("enter SaveXMLRPCServer.stop()") + if self.fut is not None: self.shutdown() self.tpe.shutdown() @@ -62,6 +69,8 @@ class SaveXMLRPCServer(SimpleXMLRPCServer): else: raise RuntimeError("save xml rpc server was not started") + proginit.logger.debug("leave SaveXMLRPCServer.stop()") + class SaveXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): @@ -75,7 +84,7 @@ class SaveXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): return False # IP-Adresse prüfen - int_acl = SaveXMLRPCServer.aclmgr.get_acllevel(self.address_string()) + int_acl = self.server.aclmgr.get_acllevel(self.address_string()) if int_acl >= 0: return True else: