Package x2go :: Package backends :: Package profiles :: Module httpbroker
[frames] | no frames]

Source Code for Module x2go.backends.profiles.httpbroker

  1  # -*- coding: utf-8 -*- 
  2   
  3  # Copyright (C) 2010-2014 by Mike Gabriel <mike.gabriel@das-netzwerkteam.de> 
  4  # 
  5  # Python X2Go is free software; you can redistribute it and/or modify 
  6  # it under the terms of the GNU Affero General Public License as published by 
  7  # the Free Software Foundation; either version 3 of the License, or 
  8  # (at your option) any later version. 
  9  # 
 10  # Python X2Go is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  # GNU Affero General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU Affero General Public License 
 16  # along with this program; if not, write to the 
 17  # Free Software Foundation, Inc., 
 18  # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 
 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  # Python X2Go modules 
 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   
46 -class X2GoSessionProfiles(base.X2GoSessionProfiles):
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 # fine-tune the URL 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 # for broker based autologin, we have to be able to provide public/private key pair 113 self.broker_my_pubkey, self.broker_my_privkey = genkeypair(local_username=_CURRENT_LOCAL_USER, client_address='127.0.0.1')
114
115 - def get_broker_noauth(self):
116 return self.broker_noauth
117
118 - def get_broker_username(self):
119 return self.broker_username
120
121 - def get_broker_url(self):
122 return self.broker_url
123
124 - def set_broker_url(self, broker_url):
125 self.broker_url = broker_url
126
127 - def get_broker_type(self):
128 return self._broker_type
129
130 - def broker_simpleauth(self, broker_username, broker_password):
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
164 - def broker_disconnect(self):
165 _profile_ids = copy.deepcopy(self.profile_ids) 166 167 # forget nearly everything... 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
183 - def is_broker_authenticated(self):
184 if self._broker_auth_successful is None: 185 # do a test auth against the given broker URL 186 try: 187 self.broker_simpleauth(self.broker_username, self.broker_password) 188 except x2go.x2go_exceptions.X2GoBrokerConnectionException: 189 self._broker_auth_successful = False 190 return self._broker_auth_successful
191
192 - def broker_listprofiles(self):
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
224 - def broker_selectsession(self, profile_id):
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
260 - def _init_profile_cache(self, profile_id):
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
294 - def _is_mutable(self, profile_id):
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
304 - def _write(self):
305 print "not suported, yet"
306
307 - def _delete_profile(self, profile_id):
308 del self.session_profiles[unicode(profile_id)]
309
310 - def _update_value(self, profile_id, option, value):
311 if type(value) is types.StringType: 312 value = unicode(value) 313 self.session_profiles[unicode(profile_id)][unicode(option)] = value
314
315 - def _get_profile_parameter(self, profile_id, option, key_type):
316 return key_type(self.session_profiles[unicode(profile_id)][unicode(option)])
317
318 - def _get_profile_options(self, profile_id):
319 return self.session_profiles[unicode(profile_id)].keys()
320
321 - def _get_profile_ids(self):
322 self.session_profiles.keys() 323 return self.session_profiles.keys()
324
325 - def _get_server_hostname(self, profile_id):
326 selected_session = self.broker_selectsession(profile_id) 327 return selected_session['server']
328
329 - def _get_server_port(self, profile_id):
330 selected_session = self.broker_selectsession(profile_id) 331 return int(selected_session['port'])
332
333 - def _get_pkey_object(self, profile_id):
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