4 from hashlib import sha1 as sha
11 Wrapper around safexmlrpc.ServerProxy to automagically add an Auth
12 struct as the first argument to every XML-RPC call. Initialize
15 (node_id, key) => BootAuth
17 session => SessionAuth
19 To authenticate using the Boot Manager authentication method, or
20 the new session-based method, respectively.
23 def __init__(self, uri, cacert, auth, timeout = 90, **kwds):
26 self.timeout = timeout
28 if isinstance(auth, (tuple, list)):
29 (self.node_id, self.key) = auth
31 elif isinstance(auth, (str, unicode)):
32 self.node_id = self.key = None
35 self.node_id = self.key = self.session = None
37 self.server = safexmlrpc.ServerProxy(self.uri, self.cacert, self.timeout, allow_none = 1, **kwds)
40 def update_session(self, f="/usr/boot/plnode.txt"):
41 # try authenticatipopulate /etc.planetlab/session
44 return [i[:-1].split('=') for i in open(f).readlines() if i.startswith(key)][0][1].strip('"')
48 auth = (int(plnode("NODE_ID")), plnode("NODE_KEY"))
49 plc = PLCAPI(self.uri, self.cacert, auth, self.timeout)
50 open("/etc/planetlab/session", 'w').write(plc.GetSession().strip())
51 self.session = open("/etc/planetlab/session").read().strip()
54 def check_authentication(self):
56 if self.key or self.session:
58 authstatus = self.AuthCheck()
60 logger.log_exc("plcapi: failed in plcapi.check_authentication")
64 def add_auth(self, function):
66 Returns a wrapper which adds an Auth struct as the first
67 argument when the function is called.
70 def canonicalize(args):
72 BootAuth canonicalization method. Parameter values are
73 collected, sorted, converted to strings, then hashed with
80 if isinstance(arg, list) or isinstance(arg, tuple):
81 # The old implementation did not recursively handle
82 # lists of lists. But neither did the old API itself.
83 values += canonicalize(arg)
84 elif isinstance(arg, dict):
85 # Yes, the comments in the old implementation are
86 # misleading. Keys of dicts are not included in the
88 values += canonicalize(arg.values())
90 # We use unicode() instead of str().
91 values.append(unicode(arg))
97 Adds an Auth struct as the first argument when the
101 if self.session is not None:
102 # Use session authentication
103 auth = {'AuthMethod': "session",
104 'session': self.session}
106 # Yes, this is the "canonicalization" method used.
107 args = canonicalize(params)
109 msg = "[" + "".join(args) + "]"
111 # We encode in UTF-8 before calculating the HMAC, which is
112 # an 8-bit algorithm.
113 digest = hmac.new(self.key, msg.encode('utf-8'), sha).hexdigest()
115 auth = {'AuthMethod': "hmac",
116 'node_id': self.node_id,
119 # Automagically add auth struct to every call
120 params = (auth,) + params
122 return function(*params)
126 def __getattr__(self, methodname):
127 function = getattr(self.server, methodname)
128 return self.add_auth(function)