8 Wrapper around safexmlrpc.ServerProxy to automagically add an Auth
9 struct as the first argument to every XML-RPC call. Initialize
12 (node_id, key) => BootAuth
14 session => SessionAuth
16 To authenticate using the Boot Manager authentication method, or
17 the new session-based method.
20 def __init__(self, uri, cacert, auth, timeout = 90, **kwds):
23 self.timeout = timeout
25 if isinstance(auth, (tuple, list)):
26 (self.node_id, self.key) = auth
28 elif isinstance(auth, (str, unicode)):
29 self.node_id = self.key = None
32 self.node_id = self.key = self.session = None
34 self.server = safexmlrpc.ServerProxy(self.uri, self.cacert, self.timeout, allow_none = 1, **kwds)
36 self.__check_authentication()
39 def __update_session(self, f="/usr/boot/plnode.txt"):
40 # try authenticatipopulate /etc.planetlab/session
43 return [i[:-1].split('=') for i in open(f).readlines() if i.startswith(key)][0][1].strip('"')
47 auth = (int(plnode("NODE_ID")), plnode("NODE_KEY"))
48 plc = PLCAPI(self.uri, self.cacert, auth, self.timeout)
49 open("/etc/planetlab/session", 'w').write(plc.GetSession().strip())
50 self.session = open("/etc/planetlab/session").read().strip()
52 def __check_authentication(self):
53 # just a simple call to check authentication
55 if (self.node_id and self.key) or self.session:
57 if self.AuthCheck() == 1: return True
62 if self.node_id and self.key:
63 # if hmac fails, just make it fail
64 raise Exception, "Unable to authenticate with hmac"
66 self.__update_session()
68 raise Exception, "Unable to authenticate with session"
71 def add_auth(self, function):
73 Returns a wrapper which adds an Auth struct as the first
74 argument when the function is called.
77 def canonicalize(args):
79 BootAuth canonicalization method. Parameter values are
80 collected, sorted, converted to strings, then hashed with
87 if isinstance(arg, list) or isinstance(arg, tuple):
88 # The old implementation did not recursively handle
89 # lists of lists. But neither did the old API itself.
90 values += canonicalize(arg)
91 elif isinstance(arg, dict):
92 # Yes, the comments in the old implementation are
93 # misleading. Keys of dicts are not included in the
95 values += canonicalize(arg.values())
97 # We use unicode() instead of str().
98 values.append(unicode(arg))
102 def wrapper(*params):
104 Adds an Auth struct as the first argument when the
108 if self.session is not None:
109 # Use session authentication
110 auth = {'AuthMethod': "session",
111 'session': self.session}
113 # Yes, this is the "canonicalization" method used.
114 args = canonicalize(params)
116 msg = "[" + "".join(args) + "]"
118 # We encode in UTF-8 before calculating the HMAC, which is
119 # an 8-bit algorithm.
120 digest = hmac.new(self.key, msg.encode('utf-8'), sha).hexdigest()
122 auth = {'AuthMethod': "hmac",
123 'node_id': self.node_id,
126 # Automagically add auth struct to every call
127 params = (auth,) + params
129 return function(*params)
133 def __getattr__(self, methodname):
134 function = getattr(self.server, methodname)
135 return self.add_auth(function)