WAMP runtime : changes from dporopat and agregorcic, adding CRA (-s) and changed way to load WAMP conf (-c)
- added Challenge Response Authentication,
- use -s commandline switch to give the shared secret.
- WAMP configuration now either given as -c commandline switch
or taken as default wampconf.json in project files.
--- a/Beremiz_service.py Tue Jan 09 14:52:56 2018 +0100
+++ b/Beremiz_service.py Tue Jan 09 15:08:08 2018 +0100
@@ -52,6 +52,7 @@
-t - enable/disable Twisted web interface (0:disable 1:enable) (default:1)
-w - web server port or "off" (default:8009)
-c - WAMP client config file or "off" (default:wampconf.json)
+ -s - WAMP client secret, given as a file or "off"
-e - python extension (absolute path .py)
working_dir - directory where are stored PLC files
@@ -70,7 +71,8 @@
given_ip = None
port = 3000
webport = 8009
-wampconf = "wampconf.json"
+wampsecret = None
+wampconf = None
servicename = None
autostart = False
enablewx = True
@@ -105,6 +107,8 @@
webport = None if a == "off" else int(a)
elif o == "-c":
wampconf = None if a == "off" else a
+ elif o == "-s":
+ wampsecret = None if a == "off" else a
elif o == "-e":
extensions.append(a)
else:
@@ -596,9 +600,21 @@
if wampconf is not None:
try:
- WC.RegisterWampClient(wampconf)
- pyruntimevars["wampsession"] = WC.GetSession
- WC.SetServer(pyroserver)
+ wampconf_project = os.path.join(WorkingDir, "wampconf.json")
+ _wampconf = WC.LoadWampClientConf(wampconf_project) # if project WAMP config is added
+
+ if not _wampconf:
+ # loaded wamp config file path forced parameter -c
+ _wampconf = WC.LoadWampClientConf(wampconf)
+ else:
+ wampconf = wampconf_project
+
+ if _wampconf and _wampconf["url"]:
+ WC.RegisterWampClient(wampconf, wampsecret)
+ pyruntimevars["wampsession"] = WC.GetSession
+ WC.SetServer(pyroserver)
+ else:
+ print(_("WAMP config is not defined."))
except Exception, e:
print(_("WAMP client startup failed. "), e)
--- a/runtime/WampClient.py Tue Jan 09 14:52:56 2018 +0100
+++ b/runtime/WampClient.py Tue Jan 09 15:08:08 2018 +0100
@@ -26,10 +26,13 @@
from __future__ import print_function
import json
+import os
+import json
from autobahn.twisted import wamp
from autobahn.twisted.websocket import WampWebSocketClientFactory, connectWS
-from autobahn.wamp import types
+from autobahn.wamp import types, auth
from autobahn.wamp.serializer import MsgPackSerializer
+from autobahn.wamp.exception import ApplicationError
from twisted.internet.defer import inlineCallbacks
from twisted.internet.protocol import ReconnectingClientFactory
@@ -66,6 +69,21 @@
class WampSession(wamp.ApplicationSession):
+ def onConnect(self):
+ secret = self.config.extra["secret"]
+ if secret:
+ user = self.config.extra["ID"].encode('utf8')
+ self.join(u"Automation", [u"wampcra"], user)
+ else:
+ self.join(u"Automation")
+
+ def onChallenge(self, challenge):
+ if challenge.method == u"wampcra":
+ secret = self.config.extra["secret"].encode('utf8')
+ signature = auth.compute_wcs(secret, challenge.extra['challenge'].encode('utf8'))
+ return signature.decode("ascii")
+ else:
+ raise Exception("don't know how to handle authmethod {}".format(challenge.method))
@inlineCallbacks
def onJoin(self, details):
@@ -100,22 +118,40 @@
def LoadWampClientConf(wampconf):
+ try:
+ WSClientConf = json.load(open(wampconf))
+ return WSClientConf
+ except ValueError, ve:
+ print(_("WAMP load error: "), ve)
+ return None
+ except Exception:
+ return None
- WSClientConf = json.load(open(wampconf))
- return WSClientConf
+def LoadWampSecret(secretfname):
+ try:
+ WSClientWampSecret = open(secretfname, 'rb').read()
+ return WSClientWampSecret
+ except ValueError, ve:
+ print(_("Wamp secret load error:"), ve)
+ return None
+ except Exception:
+ return None
-def RegisterWampClient(wampconf):
+def RegisterWampClient(wampconf, secretfname):
WSClientConf = LoadWampClientConf(wampconf)
- # start logging to console
- # log.startLogging(sys.stdout)
+ if not WSClientConf:
+ print _("WAMP client connection not established!")
+ return
+
+ WampSecret = LoadWampSecret(secretfname)
# create a WAMP application session factory
component_config = types.ComponentConfig(
realm=WSClientConf["realm"],
- extra={"ID": WSClientConf["ID"]})
+ extra=WSClientConf)
session_factory = wamp.ApplicationSessionFactory(
config=component_config)
session_factory.session = WampSession
@@ -124,9 +160,7 @@
transport_factory = ReconnectingWampWebSocketClientFactory(
session_factory,
url=WSClientConf["url"],
- serializers=[MsgPackSerializer()],
- debug=False,
- debug_wamp=False)
+ serializers=[MsgPackSerializer()])
# start the client from a Twisted endpoint
conn = connectWS(transport_factory)