1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 """\
21 L{X2GoSessionProfiles} class - managing x2goclient session profiles.
22
23 L{X2GoSessionProfiles} is a public API class. Use this class in your Python X2Go based
24 applications.
25
26 """
27 __NAME__ = 'x2gosessionprofiles-pylib'
28
29 import re
30 import requests
31 import urllib3.exceptions
32 import copy
33 import types
34 import time
35 try: import simplejson as json
36 except ImportError: import json
37
38
39 from x2go.defaults import X2GO_SESSIONPROFILE_DEFAULTS as _X2GO_SESSIONPROFILE_DEFAULTS
40 from x2go.defaults import CURRENT_LOCAL_USER as _CURRENT_LOCAL_USER
41 import x2go.backends.profiles.base as base
42 import x2go.log as log
43 from x2go.utils import genkeypair
44 import x2go.x2go_exceptions
45
47
48 defaultSessionProfile = copy.deepcopy(_X2GO_SESSIONPROFILE_DEFAULTS)
49
50 - def __init__(self, session_profile_defaults=None,
51 broker_url="http://localhost:8080/json/",
52 broker_username=None,
53 broker_password=None,
54 logger=None, loglevel=log.loglevel_DEFAULT,
55 **kwargs):
56 """\
57 Retrieve X2Go session profiles from a HTTP(S) session broker.
58
59 @param session_profile_defaults: a default session profile
60 @type session_profile_defaults: C{dict}
61 @param broker_url: URL for accessing the X2Go Session Broker
62 @type broker_url: C{str}
63 @param broker_password: use this password for authentication against the X2Go Session Broker (avoid
64 password string in the C{broker_URL} parameter is highly recommended)
65 @type broker_password: C{str}
66 @param logger: you can pass an L{X2GoLogger} object to the
67 L{x2go.backends.profiles.httpbroker.X2GoSessionProfiles} constructor
68 @type logger: L{X2GoLogger} instance
69 @param loglevel: if no L{X2GoLogger} object has been supplied a new one will be
70 constructed with the given loglevel
71 @type loglevel: C{int}
72
73 """
74 if broker_url.upper() != "HTTP":
75 match = re.match('^(?P<protocol>(http(|s)))://(|(?P<user>[a-zA-Z0-9_\.-]+)(|:(?P<password>.*))@)(?P<hostname>[a-zA-Z0-9\.-]+)(|:(?P<port>[0-9]+))($|/(?P<path>.*)$)', broker_url)
76 p = match.groupdict()
77 if p['user']:
78 self.broker_username = p['user']
79 else:
80 self.broker_username = broker_username
81 if p['password']:
82 self.broker_password = p['password']
83 elif broker_password:
84 self.broker_password = broker_password
85 else:
86 self.broker_password = None
87
88
89 p['path'] = "/{path}".format(**p)
90 if p['port'] is not None:
91 p['port'] = ":{port}".format(**p)
92
93 self.broker_url = "{protocol}://{hostname}{port}{path}".format(**p)
94
95 else:
96 self.broker_username = broker_username
97 self.broker_password = broker_password
98 self.broker_url = broker_url
99
100 self.broker_noauth = False
101 self.broker_authid = None
102 self._broker_profile_cache = {}
103 self._mutable_profile_ids = None
104 self._broker_auth_successful = None
105
106 self._broker_type = "http"
107
108 base.X2GoSessionProfiles.__init__(self, session_profile_defaults=session_profile_defaults, logger=logger, loglevel=loglevel)
109 if self.broker_url != "HTTP":
110 self.logger("Using session broker at URL: %s" % self.broker_url, log.loglevel_NOTICE)
111
112
113 self.broker_my_pubkey, self.broker_my_privkey = genkeypair(local_username=_CURRENT_LOCAL_USER, client_address='127.0.0.1')
114
116 return self.broker_noauth
117
119 return self.broker_username
120
122 return self.broker_url
123
125 self.broker_url = broker_url
126
128 return self._broker_type
129
131 if self.broker_url is not None:
132 request_data = {
133 'user': broker_username or '',
134 }
135 if self.broker_authid is not None:
136 request_data['authid'] = self.broker_authid
137 self.logger("Sending request to broker: user: {user}, authid: {authid}".format(**request_data), log.loglevel_DEBUG)
138 else:
139 if broker_password:
140 request_data['password'] = "<hidden>"
141 else:
142 request_data['password'] = "<EMPTY>"
143 self.logger("Sending request to broker: user: {user}, password: {password}".format(**request_data), log.loglevel_DEBUG)
144 request_data['password'] = broker_password or ''
145 try:
146 r = requests.post(self.broker_url, data=request_data)
147 except (requests.exceptions.ConnectionError, requests.exceptions.MissingSchema, urllib3.exceptions.LocationParseError):
148 raise x2go.x2go_exceptions.X2GoBrokerConnectionException('Failed to connect to URL %s' % self.broker_url)
149 if r.status_code == 200:
150 payload = json.loads(r.text)
151 if not self.broker_authid and not self.broker_password:
152 self.broker_noauth = True
153 elif payload.has_key('next-authid'):
154 self.broker_authid = payload['next-authid']
155 self.broker_username = broker_username or ''
156 self.broker_password = broker_password or ''
157 self._broker_auth_successful = True
158 self.populate_session_profiles()
159 return True
160 self._broker_auth_successful = False
161 self.broker_authid = None
162 return False
163
165 _profile_ids = copy.deepcopy(self.profile_ids)
166
167
168 for profile_id in _profile_ids:
169 self.init_profile_cache(profile_id)
170 try: del self._profile_metatypes[profile_id]
171 except KeyError: pass
172 try: self._profiles_need_profile_id_renewal.remove(profile_id)
173 except ValueError: pass
174 try: del self._cached_profile_ids[profile_id]
175 except KeyError: pass
176 del self.session_profiles[profile_id]
177 self._mutable_profile_ids = None
178 self._broker_auth_successful = False
179 self.broker_authid = None
180 self.broker_password = None
181 self.broker_noauth = False
182
191
193 if self.broker_url is not None:
194 request_data = {
195 'task': 'listprofiles',
196 'user': self.broker_username,
197 }
198 if self.broker_authid is not None:
199 request_data['authid'] = self.broker_authid
200 self.logger("Sending request to broker: user: {user}, authid: {authid}, task: {task}".format(**request_data), log.loglevel_DEBUG)
201 else:
202 if self.broker_password:
203 request_data['password'] = "<hidden>"
204 else:
205 request_data['password'] = "<EMPTY>"
206 self.logger("Sending request to broker: user: {user}, password: {password}, task: {task}".format(**request_data), log.loglevel_DEBUG)
207 request_data['password'] = self.broker_password or ''
208 try:
209 r = requests.post(self.broker_url, data=request_data)
210 except requests.exceptions.ConnectionError:
211 raise x2go.x2go_exceptions.X2GoBrokerConnectionException('Failed to connect to URL %s' % self.broker_url)
212 if r.status_code == 200 and r.headers['content-type'].startswith("text/json"):
213 payload = json.loads(r.text)
214 if payload.has_key('next-authid'):
215 self.broker_authid = payload['next-authid']
216 if payload.has_key('mutable_profile_ids'):
217 self._mutable_profile_ids = payload['mutable_profile_ids']
218 self._broker_auth_successful = True
219 return payload['profiles'] if payload['task'] == 'listprofiles' else {}
220 self._broker_auth_successful = False
221 self.broker_authid = None
222 return {}
223
225 if self.broker_url is not None:
226 if not self._broker_profile_cache.has_key(profile_id) or not self._broker_profile_cache[profile_id]:
227 request_data = {
228 'task': 'selectsession',
229 'profile-id': profile_id,
230 'user': self.broker_username,
231 'pubkey': self.broker_my_pubkey,
232 }
233 if self.broker_authid is not None:
234 request_data['authid'] = self.broker_authid
235 self.logger("Sending request to broker: user: {user}, authid: {authid}, task: {task}".format(**request_data), log.loglevel_DEBUG)
236 else:
237 if self.broker_password:
238 request_data['password'] = "<hidden>"
239 else:
240 request_data['password'] = "<EMPTY>"
241 self.logger("Sending request to broker: user: {user}, password: {password}, task: {task}".format(**request_data), log.loglevel_DEBUG)
242 request_data['password'] = self.broker_password or ''
243 try:
244 r = requests.post(self.broker_url, data=request_data)
245 except requests.exceptions.ConnectionError:
246 raise x2go.x2go_exceptions.X2GoBrokerConnectionException('Failed to connect to URL %s' % self.broker_url)
247 if r.status_code == 200 and r.headers['content-type'].startswith("text/json"):
248 payload = json.loads(r.text)
249 if payload.has_key('next-authid'):
250 self.broker_authid = payload['next-authid']
251 self._broker_profile_cache[profile_id] = payload['selected_session'] if payload['task'] == 'selectsession' else {}
252 self._broker_auth_successful = True
253 else:
254 self.broker_authid = None
255 self._broker_auth_successful = False
256 self._broker_profile_cache[profile_id]
257 return self._broker_profile_cache[profile_id]
258 return {}
259
261 if self._broker_profile_cache.has_key(unicode(profile_id)):
262 del self._broker_profile_cache[unicode(profile_id)]
263
265 """\
266 Populate the set of session profiles by loading the session
267 profile configuration from a file in INI format.
268
269 @return: a set of session profiles
270 @rtype: C{dict}
271
272 """
273 if self.is_broker_authenticated() and \
274 self.broker_noauth or \
275 self.broker_username and self.broker_password:
276
277 session_profiles = self.broker_listprofiles()
278 _session_profiles = copy.deepcopy(session_profiles)
279
280 for session_profile in _session_profiles:
281 session_profile = unicode(session_profile)
282 for key, default_value in self.defaultSessionProfile.iteritems():
283 key = unicode(key)
284 if type(default_value) is types.StringType:
285 default_value = unicode(default_value)
286 if not session_profiles[session_profile].has_key(key):
287 session_profiles[session_profile][key] = default_value
288
289 else:
290 session_profiles = {}
291
292 return session_profiles
293
295 if type(self._mutable_profile_ids) is types.ListType and profile_id in self._mutable_profile_ids:
296 return True
297 return False
298
300 if type(self._mutable_profile_ids) is types.ListType:
301 return True
302 return False
303
305 print "not suported, yet"
306
308 del self.session_profiles[unicode(profile_id)]
309
311 if type(value) is types.StringType:
312 value = unicode(value)
313 self.session_profiles[unicode(profile_id)][unicode(option)] = value
314
316 return key_type(self.session_profiles[unicode(profile_id)][unicode(option)])
317
319 return self.session_profiles[unicode(profile_id)].keys()
320
322 self.session_profiles.keys()
323 return self.session_profiles.keys()
324
328
330 selected_session = self.broker_selectsession(profile_id)
331 return int(selected_session['port'])
332
334 selected_session = self.broker_selectsession(profile_id)
335 if selected_session.has_key('authentication_pubkey') and selected_session['authentication_pubkey'] == 'ACCEPTED':
336 time.sleep(2)
337 return self.broker_my_privkey
338 return None
339