|
Looking at the simplest RPC call
pmnc.execute.on("target_cage").target_module.target_method(*args, **kwargs)
what implications do you observe ? Any cage appears to be capable of invoking any
method on any other cage. Besides there seems to be no call authentication
and so anyone at all appears to be capable of invoking any method on any cage.
Without nullifying any of the following discussion, I'd note that Pythomnic is
supposed to be used in a trusted network, at least the cages that exchange RPC
calls should share a private network segment, only having a perimeter cages
expose interfaces to possibly malicious clients.
Anyhow, the RPC access to a cage's methods is restricted in three ways.
First, the same way all the cages on the network share the same UDP
port for discovery broadcasts, they share an authentication key, which
is just an arbitrary string, configured in config/config_execute_auth.py.
Each call a cage issues it signs with a digital signature (HMAC) using that key,
and each call received is verified against it. Therefore, as soon as you keep
this key secret, an intruder cannot forge the call.
Still, unless you use SSL-protected RPC channels, the traffic goes in
plain and is replayable. To lock up the network really tight, roll out
your own CA, issue an SSL-certificate for each of your servers and
enable SSL RPC channels which are by disabled by default in config/startup.py
Second, any method which is expected to be called through RPC is supposed
to be clearly marked as such. For example, if your cages talk over TCP RPC channels
(the default setting, unless you enable the SSL alternative), the target_module
should look like this to have target_method invoked over RPC:
# on target cage, in target_module.py __tcp__ = [ "target_method", ... ] def target_method(...): ... # EOF
where the __tcp__ list contains the names of the accessible methods.
Third, your application code could at any moment consult the request context
for the original IP address or other authentication information about the
client which has initiated this particular request. Therefore, in security-sensitive
functions you could use something like this:
if pmnc_ctx.get("request_interface") != "__soap__" or \
not pmnc_ctx.get("request_auth_tokens")["ip"].startswith("192.168."):
raise Exception("access denied")
You can also wrap such code in a separate method or module, introduce a separate
configuration file for controlling allowed address ranges and so on.
|
Features Download Documentation Tutorial |