def replace(self, qiss, qtag, info): """ read entity configuration and replace if changed :param qiss: OP issuer qoute_plus converted :param qtag: test instance tag quote_plus converted :param info: test instance configuration as JSON document """ uqp, qp = unquote_quote(qiss, qtag) logger.info('Replace config: iss="{}", tag="{}"'.format(*uqp)) try: _js = json.loads(info) except Exception as err: _desc = 'Bogus replacement info!: {}'.format(info) logger.error(_desc) return cherrypy.HTTPError(404, _desc) try: _js0 = self.read_conf(qiss, qtag) except (TypeError, NoSuchFile): path = '{}/{}'.format(qiss, qtag) return cherrypy.HTTPError(404, 'Could not find {}'.format(path)) if _js == _js0: # don't bother pass else: self.write(qiss, qtag, json.dumps(_js)) return b'OK'
def run(self, iss='', tag='', ev=None, **kwargs): uqp, qp = unquote_quote(iss, tag) logger.info('Run iss="{}", tag="{}"'.format(*uqp)) self.store_edit(qp, **kwargs) return self.restart_instance(iss, tag, 'start')
def construct_config(self, qiss, qtag): uqp, qp = unquote_quote(qiss, qtag) logger.info('construct config iss="{}", tag="{}"'.format(*uqp)) if not qtag: raise Exception('Missing "tag" value') _conf = json.loads( open('{}/common.json'.format(self.entinfo), 'r').read()) typ, _econf = self.read_conf(*qp) if _econf is None: raise Exception('No configuration for {}:{}'.format(*uqp)) if do_registration(_econf['tool']['profile']): reg_info = json.loads( open('{}/registration_info.json'.format(self.entinfo), 'r').read()) _conf['client']['registration_info'] = reg_info[ 'registration_info'] else: try: _conf['client']['registration_response'] = _econf['client'][ 'registration_response'] except KeyError: _conf['client']['registration_response'] = _econf[ 'registration_response'] if not do_discovery(_econf['tool']['profile']): _conf['client']['provider_info'] = _econf['provider_info'] _conf['tool'] = _econf['tool'] logger.info("Constructed config: {}".format(_conf)) return _conf
def list_dir(self, dirname, qiss): uqp, qp = unquote_quote(qiss) logger.info('List directory: iss="{}"'.format(uqp[0])) if not os.path.isdir(dirname): if qp[0].endswith('%2F'): # try to remove qp[0] = qp[0][:-3] else: # else add qp[0] += '%2F' dirname = self.entity_file_name(qp[0], '') if not os.path.isdir(dirname): raise ValueError(dirname) res = ['<p>'] for file in os.listdir(dirname): _url = '{}{}/{}'.format(self.base_url, qp[0], quote_plus(file)) res.append('<a href="{}">{}</a><br>'.format(_url, file)) res.append('</p') _html = [ '<html><head>List of tags for "{}"</head>'.format(uqp[0]), '<body>' ] _html.extend(res) _html.append('</body></html>') return 'html', '\n'.join(_html)
def run(self, iss='', tag='', ev=None, **kwargs): uqp, qp = unquote_quote(iss, tag) logger.info('Run iss="{}", tag="{}"'.format(*uqp)) self.store_edit(qp, **kwargs) return self.restart_instance(iss, tag, 'start')
def restart_instance(self, iss, tag, action='restart'): uqp, qp = unquote_quote(iss, tag) logger.info('{} iss="{}", tag="{}"'.format(action, uqp[0], uqp[1])) url = self.app.run_test_instance(qp[0], qp[1]) if isinstance(url, Response): return conv_response(None, url) if url: args = { 'title': "Action performed", 'base': self.baseurl, 'note': 'Your test instance "{iss}:{tag}" has been ' '{act} as <a href="{url}">{url}</a>'.format(iss=uqp[0], tag=uqp[1], url=url, act=action) } else: args = { 'title': "Action Failed", 'base': self.baseurl, 'note': 'Could not {} your test instance'.format(action) } _msg = self.html['message.html'].format(**args) return as_bytes(_msg)
def list_tag(self, iiss): uqp, qp = unquote_quote(iiss) logger.info('List all tags for "{}"'.format(uqp[0])) iss = uqp[0] qiss = qp[0] try: fils = os.listdir(os.path.join(self.entpath, qiss)) except FileNotFoundError: logger.warning('No such Issuer exists') return b"No such Issuer exists" active = dict() tags = [] for fil in fils: tag = unquote_plus(fil) active[tag] = isrunning(iss, tag) tags.append(tag) logger.info('tags: {}'.format(tags)) self.assigned_ports.load() _msg = self.prehtml['list_tag.html'].format(item_table=item_table( qiss, tags, active, self.assigned_ports, self.test_tool_base), iss=iss, version=self.version) return as_bytes(_msg)
def update(self, iss, tag, ev=None, **kwargs): """ Displays interface for updating configuration :param iss: Issuer ID :param tag: tag :param ev: Event instance :param kwargs: keyword arguments :return: """ logger.debug('update test tool configuration: {} {}'.format(iss, tag)) uqp, qp = unquote_quote(iss, tag) try: _format, _conf = self.rest.read_conf(qp[0], qp[1]) except TypeError: _msg = "No such test tool configuration" logger.info(_msg) else: logger.info('config: {}'.format(_conf)) dicts, state, multi, notes = update_config(_conf, self.tool_params) action = "{}/run/{}/{}".format('', qp[0], qp[1]) _msg = self.html['instance.html'].format(display=display( dicts, state, multi, notes, action), version=self.version) return as_bytes(_msg)
def restart(self, iss, tag, ev): """ Restart a test instance :param iss: :param tag: :param ev: :return: """ logger.info('restart test tool: {} {}'.format(iss, tag)) uqp, qp = unquote_quote(iss, tag) url = self.app.run_test_instance(*qp) if isinstance(url, Response): return conv_response(None, url) if url: # redirect back to entity page loc = '{}entity/{}'.format(self.rest.base_url, qp[0]) raise cherrypy.HTTPRedirect(loc) else: args = { 'title': "Action Failed", 'base': self.baseurl, 'note': 'Could not restart your test instance'} _msg = self.html['message.html'].format(**args) return as_bytes(_msg)
def update(self, iss, tag, ev=None, **kwargs): """ Displays interface for updating configuration :param iss: Issuer ID :param tag: tag :param ev: Event instance :param kwargs: keyword arguments :return: """ logger.debug('update test tool configuration: {} {}'.format(iss, tag)) uqp, qp = unquote_quote(iss, tag) try: _format, _conf = self.rest.read_conf(qp[0], qp[1]) except TypeError: _msg = "No such test tool configuration" logger.info(_msg) else: logger.info('config: {}'.format(_conf)) dicts, state, multi, notes = update_config(_conf, self.tool_params) action = "{}/run/{}/{}".format('', qp[0], qp[1]) _msg = self.html['instance.html'].format( display=display(dicts, state, multi, notes, action), version=self.version ) return as_bytes(_msg)
def list_tag(self, iiss): uqp, qp = unquote_quote(iiss) logger.info('List all tags for "{}"'.format(uqp[0])) iss = uqp[0] qiss = qp[0] try: fils = os.listdir(os.path.join(self.entpath, qiss)) except FileNotFoundError: logger.warning('No such Issuer exists') return b"No such Issuer exists" active = dict() tags = [] for fil in fils: tag = unquote_plus(fil) active[tag] = isrunning(iss, tag) tags.append(tag) logger.info('tags: {}'.format(tags)) self.assigned_ports.load() _msg = self.prehtml['list_tag.html'].format( item_table=item_table(qiss, tags, active, self.assigned_ports, self.test_tool_base), iss=iss, version=self.version ) return as_bytes(_msg)
def restart(self, iss, tag, ev): """ Restart a test instance :param iss: :param tag: :param ev: :return: """ logger.info('restart test tool: {} {}'.format(iss, tag)) uqp, qp = unquote_quote(iss, tag) url = self.app.run_test_instance(*qp) if isinstance(url, Response): return conv_response(None, url) if url: # redirect back to entity page loc = '{}entity/{}'.format(self.rest.base_url, qp[0]) raise cherrypy.HTTPRedirect(loc) else: args = { 'title': "Action Failed", 'base': self.baseurl, 'note': 'Could not restart your test instance' } _msg = self.html['message.html'].format(**args) return as_bytes(_msg)
def create(self, **kwargs): logging.info('create test tool configuration') # construct profile profile = to_profile(kwargs) _ent_conf = create_model(profile, ent_info_path=self.ent_info_path) state = {} if not do_discovery(profile): _ent_conf['client']['provider_info']['issuer'] = kwargs['iss'] if not do_registration(profile): # need to create a redirect_uri, means I need to register a port _port = self.app.assigned_ports.register_port( kwargs['iss'], kwargs['tag']) if self.app.test_tool_base.endswith('/'): _base = self.app.test_tool_base[:-1] else: _base = self.app.test_tool_base _ent_conf['client']['registration_response'][ 'redirect_uris'] = '{}:{}/authz_cb'.format(_base, _port) uqp, qp = unquote_quote(kwargs['iss'], kwargs['tag']) _ent_conf['tool']['issuer'] = uqp[0] _ent_conf['tool']['tag'] = uqp[1] _ent_conf['tool']['profile'] = profile _ent_conf.update(from_profile(profile)) logging.info("Test tool config: {}".format(_ent_conf)) self.rest.write(qp[0], qp[1], _ent_conf) # Do a redirect raise cherrypy.HTTPRedirect('/action/update?iss={}&tag={}'.format( qp[0], qp[1]))
def store(self, qiss, qtag, info): """ :param qiss: OP issuer qoute_plus converted :param qtag: test instance tag quote_plus converted :param info: test instance configuration as JSON document :return: HTTP Created is successful """ uqp, qp = unquote_quote(qiss, qtag) logger.info('Store config: iss="{}", tag="{}", info={}'.format( uqp[0], uqp[1], info)) # verify the soundness of the information if isinstance(info, dict): info = json.dumps(info) else: try: json.loads(info) except Exception as err: _desc = 'Bogus replacement info!: {}'.format(info) logger.error(_desc) return cherrypy.HTTPError(404, _desc) self.write(qiss, qtag, info) fname = '{}{}/{}'.format(self.base_url, qiss, qtag) cherrypy.response.status = 201 return as_bytes(fname)
def backup(self, iiss, itag): uqp, qp = unquote_quote(iiss, itag) logger.info('Do backup of iss="{}", tag="{}"'.format(*uqp)) info = open(os.path.join(self.entpath, *qp), 'r').read() bname = '{}.{}.{}'.format(qp[0], qp[1], time.time()) fp = open(os.path.join(self.backup, bname), 'w') fp.write(info) fp.close() return ''
def backup(self, iiss, itag): uqp, qp = unquote_quote(iiss, itag) logger.info('Do backup of iss="{}", tag="{}"'.format(*uqp)) info = open(os.path.join(self.entpath, *qp), 'r').read() bname = '{}.{}.{}'.format(qp[0], qp[1], time.time()) fp = open(os.path.join(self.backup, bname), 'w') fp.write(info) fp.close() return ''
def stop(self, iss, tag, ev): logger.info('stop test tool: {} {}'.format(iss, tag)) # If already running - kill self.kill(iss, tag, ev) uqp, qp = unquote_quote(iss, tag) # redirect back to entity page loc = '{}entity/{}'.format(self.rest.base_url, qp[0]) raise cherrypy.HTTPRedirect(loc)
def stop(self, iss, tag, ev): logger.info('stop test tool: {} {}'.format(iss, tag)) # If already running - kill self.kill(iss, tag, ev) uqp, qp = unquote_quote(iss, tag) # redirect back to entity page loc = '{}entity/{}'.format(self.rest.base_url, qp[0]) raise cherrypy.HTTPRedirect(loc)
def show_tag(self, iiss, itag): uqp, qp = unquote_quote(iiss, itag) logger.info('Show info on iss="{}", tag="{}"'.format(*uqp)) if find_test_instance(*uqp): active = '<div class="active"> Running </div>' else: active = '<div class="inactive"> Inactive </div>' info = open(os.path.join(self.entpath, *qp), 'r').read() _msg = self.prehtml['action.html'].format(path=qp[-1], active=active, display_info=info) return as_bytes(_msg)
def show_tag(self, iiss, itag): uqp, qp = unquote_quote(iiss, itag) logger.info('Show info on iss="{}", tag="{}"'.format(*uqp)) if find_test_instance(*uqp): active = '<div class="active"> Running </div>' else: active = '<div class="inactive"> Inactive </div>' info = open(os.path.join(self.entpath, *qp), 'r').read() _msg = self.prehtml['action.html'].format(path=qp[-1], active=active, display_info=info) return as_bytes(_msg)
def create(self, **kwargs): logger.info('create test tool configuration: {} {}'.format( kwargs['iss'], kwargs['tag'])) uqp, qp = unquote_quote(kwargs['iss'], kwargs['tag']) if not uqp[0].startswith('https://') and not uqp[0].startswith( 'http://'): err = 'issuer value must start with "https://" or "http://"' logger.error(err) return as_bytes('Sorry failed to create: {}'.format(err)) # construct profile try: profile = to_profile(kwargs) except KeyError as err: logger.error(err) return as_bytes('Sorry failed to create: {}'.format(err)) _ent_conf = create_model(profile, ent_info_path=self.ent_info_path) if not do_discovery(profile): _ent_conf['client']['provider_info']['issuer'] = kwargs['iss'] if not do_registration(profile): # need to create a redirect_uri, means I need to register a port _port = self.app.assigned_ports.register_port( kwargs['iss'], kwargs['tag']) if self.app.test_tool_base.endswith('/'): _base = self.app.test_tool_base[:-1] else: _base = self.app.test_tool_base _ent_conf['client']['registration_response'][ 'redirect_uris'] = '[ "{}:{}/authz_cb", "{}:{}/authz_post" ]'.format( _base, _port, _base, _port) _ent_conf['tool']['issuer'] = uqp[0] _ent_conf['tool']['tag'] = uqp[1] _ent_conf['tool']['profile'] = profile _ent_conf.update(from_profile(profile)) logger.info("Test tool config: {}".format(_ent_conf)) self.rest.write(qp[0], qp[1], _ent_conf) # Do a redirect raise cherrypy.HTTPRedirect('/action/update?iss={}&tag={}'.format( qp[0], qp[1]))
def kill(self, iss, tag, ev): uqp, qp = unquote_quote(iss, tag) _key = self.app.assigned_ports.make_key(*uqp) try: pid = isrunning(unquote_plus(iss), unquote_plus(tag)) except KeyError: pass else: if pid: # logger.info('kill {}'.format(pid)) # subprocess.call(['kill', str(pid)]) kill_process(pid) try: del self.app.running_processes[_key] except KeyError: pass
def kill(self, iss, tag, ev): uqp, qp = unquote_quote(iss, tag) _key = self.app.assigned_ports.make_key(*uqp) try: pid = isrunning(unquote_plus(iss), unquote_plus(tag)) except KeyError: pass else: if pid: # logger.info('kill {}'.format(pid)) # subprocess.call(['kill', str(pid)]) kill_process(pid) try: del self.app.running_processes[_key] except KeyError: pass
def create(self, **kwargs): logger.info( 'create test tool configuration: {} {}'.format(kwargs['iss'], kwargs['tag'])) uqp, qp = unquote_quote(kwargs['iss'], kwargs['tag']) if not uqp[0].startswith('https://') and not uqp[0].startswith('http://'): err = 'issuer value must start with "https://" or "http://"' logger.error(err) return as_bytes('Sorry failed to create: {}'.format(err)) # construct profile try: profile = to_profile(kwargs) except KeyError as err: logger.error(err) return as_bytes('Sorry failed to create: {}'.format(err)) _ent_conf = create_model(profile, ent_info_path=self.ent_info_path) if not do_discovery(profile): _ent_conf['client']['provider_info']['issuer'] = kwargs['iss'] if not do_registration(profile): # need to create a redirect_uri, means I need to register a port _port = self.app.assigned_ports.register_port(kwargs['iss'], kwargs['tag']) if self.app.test_tool_base.endswith('/'): _base = self.app.test_tool_base[:-1] else: _base = self.app.test_tool_base _ent_conf['client']['registration_response'][ 'redirect_uris'] = '[ "{}:{}/authz_cb", "{}:{}/authz_post" ]'.format(_base, _port, _base, _port) _ent_conf['tool']['issuer'] = uqp[0] _ent_conf['tool']['tag'] = uqp[1] _ent_conf['tool']['profile'] = profile _ent_conf.update(from_profile(profile)) logger.info("Test tool config: {}".format(_ent_conf)) self.rest.write(qp[0], qp[1], _ent_conf) # Do a redirect raise cherrypy.HTTPRedirect( '/action/update?iss={}&tag={}'.format(qp[0], qp[1]))
def read_conf(self, qiss, qtag): """ :param qiss: OP issuer qoute_plus converted :param qtag: test instance tag quote_plus converted :return: Returns the instance configuration as a dictionary """ uqp, qp = unquote_quote(qiss, qtag) logger.info('Read config: iss="{}", tag="{}"'.format(*uqp)) fname = self.entity_file_name(*qp) if fname: if not os.path.isfile(fname): if qp[0].endswith('%2F'): # try to remove qp[0] = qp[0][:-3] else: # else add qp[0] += '%2F' fname = self.entity_file_name(qp[0], qp[1]) if not os.path.isfile(fname): logger.error('No such file') raise NoSuchFile(fname) # return self.list_dir(fname, qiss) try: _data = open(fname, 'r').read() except Exception as err: if sys.version[0] == '2': if isinstance(err, IOError): return None else: raise NoSuchFile(fname) elif isinstance(err, FileNotFoundError): return None else: logger.error('Unable to read from file: {}'.format(fname)) raise NoSuchFile(fname) try: return 'json', json.loads(_data) except Exception as err: logger.error(err) return None else: return None
def restart_instance(self, iss, tag, action='restart'): uqp, qp = unquote_quote(iss, tag) logger.info('{} iss="{}", tag="{}"'.format(action, uqp[0], uqp[1])) url = self.app.run_test_instance(qp[0], qp[1]) if isinstance(url, Response): return conv_response(None, url) if url: args = { 'title': "Action performed", 'base': self.baseurl, 'note': 'Your test instance "{iss}:{tag}" has been ' '{act} as <a href="{url}">{url}</a>'.format( iss=uqp[0], tag=uqp[1], url=url, act=action)} else: args = { 'title': "Action Failed", 'base': self.baseurl, 'note': 'Could not {} your test instance'.format(action)} _msg = self.html['message.html'].format(**args) return as_bytes(_msg)
def restore(self, iiss, itag): uqp, qp = unquote_quote(iiss, itag) logger.info('Restore iss="{}", tag="{}"'.format(*uqp)) bname = '{}.{}'.format(qp[0], qp[1]) last = 0.0 last_backup = None for item in os.listdir(self.backup): if item.startswith("."): continue if not itag.startswith(bname): continue # Should be 3 parts, only interested in the last p = item.split('.')[-1] if float(p) > last: last = float(p) last_backup = item if last_backup: fn = os.path.join(self.backup, last_backup) info = open(fn, 'r').read() return self.rest.store(qp[0], qp[1], info)
def delete(self, iss, tag, ev, pid=0): logger.info('delete test tool configuration: {} {}'.format(iss, tag)) # If already running - kill self.kill(iss, tag, ev) uqp, qp = unquote_quote(iss, tag) _key = self.app.assigned_ports.make_key(*uqp) os.unlink(os.path.join(self.entpath, *qp)) # Remove issuer if out of tags if not os.listdir(os.path.join(self.entpath, qp[0])): os.rmdir(os.path.join(self.entpath, qp[0])) try: del self.app.assigned_ports[_key] except KeyError: # How could it already have gone ? Ah, well pass # redirect back to entity page loc = '{}entity'.format(self.rest.base_url) raise cherrypy.HTTPRedirect(loc)
def delete(self, iss, tag, ev, pid=0): logger.info('delete test tool configuration: {} {}'.format(iss, tag)) # If already running - kill self.kill(iss, tag, ev) uqp, qp = unquote_quote(iss, tag) _key = self.app.assigned_ports.make_key(*uqp) os.unlink(os.path.join(self.entpath, *qp)) # Remove issuer if out of tags if not os.listdir(os.path.join(self.entpath, qp[0])): os.rmdir(os.path.join(self.entpath, qp[0])) try: del self.app.assigned_ports[_key] except KeyError: # How could it already have gone ? Ah, well pass # redirect back to entity page loc = '{}entity'.format(self.rest.base_url) raise cherrypy.HTTPRedirect(loc)
def restore(self, iiss, itag): uqp, qp = unquote_quote(iiss, itag) logger.info('Restore iss="{}", tag="{}"'.format(*uqp)) bname = '{}.{}'.format(qp[0], qp[1]) last = 0.0 last_backup = None for item in os.listdir(self.backup): if item.startswith("."): continue if not itag.startswith(bname): continue # Should be 3 parts, only interested in the last p = item.split('.')[-1] if float(p) > last: last = float(p) last_backup = item if last_backup: fn = os.path.join(self.backup, last_backup) info = open(fn, 'r').read() return self.rest.store(qp[0], qp[1], info)
def stop(self, iss, tag, ev): logger.info('stop test tool') uqp, qp = unquote_quote(iss, tag) _key = self.app.assigned_ports.make_key(*uqp) # If already running - kill try: pid = isrunning(unquote_plus(iss), unquote_plus(tag)) except KeyError: pass else: if pid: #logger.info('kill {}'.format(pid)) #subprocess.call(['kill', str(pid)]) kill_process(pid) try: del self.app.running_processes[_key] except KeyError: pass # redirect back to entity page loc = '{}entity/{}'.format(self.rest.base_url, qp[0]) raise cherrypy.HTTPRedirect(loc)