def setUp(self): super(SimplePipeLineTest, self).setUp() self.templates = TemplateLookup( directories=[os.path.join(self.datadir, 'simple-pipeline')]) self.output = tempfile.NamedTemporaryFile('w').name self.signer = tempfile.NamedTemporaryFile('w').name self.signer_template = self.templates.get_template('signer.fd') self.validator = tempfile.NamedTemporaryFile('w').name self.validator_template = self.templates.get_template('validator.fd') self.md_signer = MDRepository(store=MemoryStore()) self.md_validator = MDRepository(store=MemoryStore()) with open(self.signer, "w") as fd: fd.write(self.signer_template.render(ctx=self)) with open(self.validator, "w") as fd: fd.write(self.validator_template.render(ctx=self)) self.signer_result = plumbing(self.signer).process(self.md_signer, state={ 'batch': True, 'stats': {} }) self.validator_result = plumbing(self.validator).process( self.md_validator, state={ 'batch': True, 'stats': {} })
def __init__(self, pipes=None, autoreload=False, frequency=600, aliases=None, cache_enabled=True, observers=None, store=None): if aliases is None: aliases = ATTRS if not observers: observers = [] if not pipes: pipes = [] self._pipes = pipes self.cache_enabled = cache_enabled self.lock = ReadWriteLock() self.plumbings = [plumbing(v) for v in pipes] self.refresh = MDUpdate(cherrypy.engine, server=self, frequency=frequency) self.refresh.subscribe() self.aliases = aliases self.psl = PublicSuffixList() self.md = MDRepository(metadata_cache_enabled=self.cache_enabled, store=store) if autoreload: for f in pipes: cherrypy.engine.autoreload.files.add(f)
def setUp(self): self.md = MDRepository(store=MemoryStore) self.datadir = resource_filename('metadata', 'test/data') self.xml_source = os.path.join(self.datadir, 'test01.xml') self.swamid_source = os.path.join(self.datadir, 'swamid-2.0-test.xml') self.swamid = root(parse_xml(self.swamid_source)) self.t = parse_xml(self.xml_source) self.non_metadata = parse_xml(resource_filename("not-metadata.xml", self.datadir))
def _get_metadata_stream(self, load_streams): try: load = [] select = [] count = 1 for stream in load_streams: curid = "%s%d" % (self.slug, count) load.append("%s as %s" % (stream[0], curid)) if stream[1] == 'SP' or stream[1] == 'IDP': select.append( "%s!//md:EntityDescriptor[md:%sSSODescriptor]" % (curid, stream[1])) else: select.append("%s" % curid) count = count + 1 if len(select) > 0: pipeline = [{'load': load}, {'select': select}] else: pipeline = [{'load': load}, 'select'] md = MDRepository() entities = Plumbing(pipeline=pipeline, id=self.slug).process(md, state={ 'batch': True, 'stats': {} }) return etree.tostring(entities) except Exception, e: raise Exception('Getting metadata from %s failed.\nError: %s' % (load_streams, e))
def __init__(self, pipes=None, observers=None): if not observers: observers = [] if not pipes: pipes = [] self._pipes = pipes self.lock = ReadWriteLock() self.plumbings = [plumbing(v) for v in pipes] self.refresh = MDUpdate(cherrypy.engine, server=self, frequency=config.frequency) self.refresh.subscribe() self.aliases = config.aliases self.psl = PublicSuffixList() self.md = MDRepository(metadata_cache_enabled=config.caching_enabled, store=config.store) if config.autoreload: for f in pipes: cherrypy.engine.autoreload.files.add(f)
def exec_pipeline(self, pstr): md = MDRepository() p = yaml.load(StringIO(pstr)) print(p) res = Plumbing(p, pid="test").process(md, state={ 'batch': True, 'stats': {} }) return res, md
def run_pipeline(self, pl_name, ctx=None, md=MDRepository()): if ctx is None: ctx = dict() templates = TemplateLookup(directories=[os.path.join(self.datadir, 'simple-pipeline')]) pipeline = tempfile.NamedTemporaryFile('w').name template = templates.get_template(pl_name) with open(pipeline, "w") as fd: fd.write(template.render(ctx=ctx)) res = plumbing(pipeline).process(md, state={'batch': True, 'stats': {}}) os.unlink(pipeline) return res, md, ctx
class MDServer(object): """The MDServer class is the business logic of pyFF. This class is isolated from the request-decoding logic of MDRoot and from the ancilliary classes like MDStats and WellKnown. """ def __init__(self, pipes=None, observers=None): if not observers: observers = [] if not pipes: pipes = [] self._pipes = pipes self.lock = ReadWriteLock() self.plumbings = [plumbing(v) for v in pipes] self.refresh = MDUpdate(cherrypy.engine, server=self, frequency=config.frequency) self.refresh.subscribe() self.aliases = config.aliases self.psl = PublicSuffixList() self.md = MDRepository(metadata_cache_enabled=config.caching_enabled, store=config.store) if config.autoreload: for f in pipes: cherrypy.engine.autoreload.files.add(f) @property def ready(self): return self.md.store.ready() def reload_pipeline(self): new_plumbings = [plumbing(v) for v in self._pipes] self.plumbings = new_plumbings class MediaAccept(object): def __init__(self): pass def has_key(self, key): return True def get(self, item): return self.__getitem__(item) def __getitem__(self, item): try: return cptools.accept(item, debug=True) except HTTPError: return False def request(self, **kwargs): """The main request processor. This code implements all rendering of metadata. """ stats['MD Requests'] += 1 if not self.ready: raise HTTPError(503, _("Service Unavailable (repository loading)")) pfx = kwargs.get('pfx', None) path = kwargs.get('path', None) content_type = kwargs.get('content_type', None) log.debug("MDServer pfx=%s, path=%s, content_type=%s" % (pfx, path, content_type)) def _d(x, do_split=True): if x is not None: x = x.strip() log.debug("_d(%s,%s)" % (x, do_split)) if x is None or len(x) == 0: return None, None if x.startswith("{base64}"): x = x[8:].decode('base64') if do_split and '.' in x: (pth, dot, extn) = x.rpartition('.') assert (dot == '.') if extn in _ctypes: return pth, extn return x, None _ctypes = {'xml': 'application/xml', 'json': 'application/json', 'htm': 'text/html', 'html': 'text/html', 'ds': 'text/html', 's': 'application/json'} alias = None if pfx: alias = pfx pfx = self.aliases.get(alias, None) if pfx is None: raise NotFound() path, ext = _d(path, content_type is None) if pfx and path: q = "{%s}%s" % (pfx, path) path = "/%s/%s" % (alias, path) else: q = path if ext is not None: log.debug("request path: %s.%s, headers: %s" % (path, ext, cherrypy.request.headers)) else: log.debug("request path: %s, headers: %s" % (path, cherrypy.request.headers)) accept = {} if content_type is None: if ext is not None and ext in _ctypes: accept = {_ctypes[ext]: True} else: accept = MDServer.MediaAccept() if ext is not None: path = "%s.%s" % (path, ext) else: accept = {content_type: True} with self.lock.readlock: if ext == 'ds': pdict = dict() entity_id = kwargs.get('entityID', None) if entity_id is None: raise HTTPError(400, _("400 Bad Request - missing entityID")) pdict['sp'] = self.md.sha1_id(entity_id) e = self.md.store.lookup(entity_id) if e is None or len(e) == 0: raise HTTPError(404) if len(e) > 1: raise HTTPError(400, _("400 Bad Request - multiple matches for") + " %s" % entity_id) pdict['entity'] = self.md.simple_summary(e[0]) if not path: pdict['search'] = "/search/" pdict['list'] = "/role/idp.json" else: pdict['search'] = "%s.s" % path pdict['list'] = "%s.json" % path cherrypy.response.headers['Content-Type'] = 'text/html' return render_template("ds.html", **pdict) elif ext == 's': paged = bool(kwargs.get('paged', False)) query = kwargs.get('query', None) page = kwargs.get('page', 0) page_limit = kwargs.get('page_limit', 10) entity_filter = kwargs.get('entity_filter', None) related = kwargs.get('related', None) cherrypy.response.headers['Content-Type'] = 'application/json' if query is None: log.debug("empty query - creating one") query = [cherrypy.request.remote.ip] referrer = cherrypy.request.headers.get('referrer', None) if referrer is not None: log.debug("including referrer: %s" % referrer) url = urlparse.urlparse(referrer) host = url.netloc if ':' in url.netloc: (host, port) = url.netloc.split(':') for host_part in host.rstrip(self.psl.get_public_suffix(host)).split('.'): if host_part is not None and len(host_part) > 0: query.append(host_part) log.debug("created query: %s" % ",".join(query)) if paged: res, more, total = self.md.search(query, path=q, page=int(page), page_limit=int(page_limit), entity_filter=entity_filter, related=related) # log.debug(dumps({'entities': res, 'more': more, 'total': total})) return dumps({'entities': res, 'more': more, 'total': total}) else: return dumps(self.md.search(query, path=q, entity_filter=entity_filter, related=related)) elif accept.get('text/html'): if not q: if pfx: title = pfx else: title = _("Metadata By Attributes") return render_template("index.html", md=self.md, alias=alias, aliases=self.aliases, title=title) else: entities = self.md.lookup(q) if not entities: raise NotFound() if len(entities) > 1: return render_template("metadata.html", md=self.md, subheading=q, entities=entities) else: entity = entities[0] t = html.fragment_fromstring(unicode(xslt_transform(entity, "entity2html.xsl"))) for c_elt in t.findall(".//code[@role='entity']"): c_txt = dumptree(entity) parser = etree.XMLParser(remove_blank_text=True) src = StringIO(c_txt) tree = etree.parse(src, parser) c_txt = dumptree(tree, pretty_print=True, xml_declaration=False).decode("utf-8") p = c_elt.getparent() p.remove(c_elt) if p.text is not None: p.text += c_txt else: p.text = c_txt xml = dumptree(t, xml_declaration=False).decode('utf-8') return render_template("entity.html", headline=self.md.display(entity).strip(), subheading=entity.get('entityID'), entity_id=entity.get('entityID'), content=xml) else: for p in self.plumbings: state = {'request': True, 'headers': {'Content-Type': 'text/xml'}, 'accept': accept, 'url': cherrypy.url(relative=False), 'select': q, 'path': path, 'stats': {}} r = p.process(self.md, state=state) if r is not None: cache_ttl = state.get('cache', 0) log.debug("caching for %d seconds" % cache_ttl) for k, v in state.get('headers', {}).iteritems(): cherrypy.response.headers[k] = v caching.expires(secs=cache_ttl) return r raise NotFound()
class TestRepo(TestCase): def setUp(self): self.md = MDRepository(store=MemoryStore) self.datadir = resource_filename('metadata', 'test/data') self.xml_source = os.path.join(self.datadir, 'test01.xml') self.swamid_source = os.path.join(self.datadir, 'swamid-2.0-test.xml') self.swamid = root(parse_xml(self.swamid_source)) self.t = parse_xml(self.xml_source) self.non_metadata = parse_xml(resource_filename("not-metadata.xml", self.datadir)) def test_md_exists(self): assert (self.md is not None) def test_clone(self): entity_id = root(self.t).get('entityID') self.md.store.update(root(self.t), entity_id) nmd = self.md.clone() assert (nmd.store.size() == self.md.store.size()) assert (nmd.lookup(entity_id) is not None) def test_sha1_hash(self): entity_id = root(self.t).get('entityID') self.md.store.update(root(self.t), entity_id) e = self.md.lookup(entity_id) assert (self.md.sha1_id(e[0]) == "{sha1}568515f6fae8c8b4d42d543853c96d08f051ef13") assert (hash_id(e[0], 'sha1', prefix=False) == "568515f6fae8c8b4d42d543853c96d08f051ef13") def test_entity_attribute(self): entity_id = root(self.t).get('entityID') self.md.set_entity_attributes(root(self.t), {"http://ns.example.org": "foo"}) self.md.store.update(root(self.t), entity_id) e = self.md.lookup("{%s}%s" % ("http://ns.example.org", 'foo'))[0] assert (e is not None) assert (e.get('entityID') == entity_id) def test_utils(self): entity_id = root(self.t).get('entityID') self.md.store.update(root(self.t), entity_id) e = self.md.lookup(entity_id)[0] assert (self.md.is_idp(e)) assert (not self.md.is_sp(e)) assert (self.md.icon(e) in ['https://www.example.com/static/images/logo.jpg', 'https://www.example.com/static/images/logo_eng.jpg'] ) domains = self.md.domains(e) assert ('example.com' in domains) assert ('example.net' in domains) assert ('idp.example.com' not in domains) assert ('foo.com' not in domains) edup = deepcopy(e) name, desc = self.md.ext_display(e) assert(name == 'Example University') assert(desc == 'Identity Provider for Example University') disp = self.md.display(e) assert (disp == 'Example University') for elt in e.findall(".//{%s}DisplayName" % NS['mdui']): elt.getparent().remove(elt) disp = self.md.display(e) assert (disp == 'The Example University') for elt in e.findall(".//{%s}OrganizationDisplayName" % NS['md']): elt.getparent().remove(elt) disp = self.md.display(e) assert (disp == 'ExampleU') for elt in e.findall(".//{%s}OrganizationName" % NS['md']): elt.getparent().remove(elt) disp = self.md.display(e) assert (disp == entity_id) e = edup subs = self.md.sub_domains(e) assert ('example.com' in subs) assert ('example.net' in subs) assert ('idp.example.com' not in subs) summary = self.md.simple_summary(e) assert (summary['title'] == 'Example University') assert (summary['descr'] == 'Identity Provider for Example University') assert (summary['value'] == entity_id) assert ('icon' in summary) assert ('icon_url' in summary and summary['icon'] == summary['icon_url']) assert ('domains' in summary) assert ('id' in summary) empty = self.md.simple_summary(None) assert (not empty) def test_display(self): swamid = root(self.swamid) self.md.store.update(swamid, swamid.get('Name')) funet_connect = self.md.lookup('https://connect.funet.fi/shibboleth')[0] name, desc = self.md.ext_display(funet_connect) assert(name == 'FUNET E-Meeting Service') dn = self.md.display(funet_connect) def test_missing(self): swamid = root(self.swamid) self.md.store.update(swamid, swamid.get('Name')) missing = self.md.lookup('https://connect.funet.fi/shibboleth+missing') assert (len(missing) == 0) def test_non_metadata(self): e = root(self.non_metadata) assert self.md.expiration(e) is None try: self.md.annotate(e,"kaka","x","y") self.md.set_entity_attributes(e, dict(a=1)) assert False except MetadataException: pass
class TestRepo(TestCase): def setUp(self): self.md = MDRepository() self.md.store = self.md.store_class() self.datadir = resource_filename('metadata', 'test/data') self.xml_source = os.path.join(self.datadir, 'test01.xml') self.swamid_source = os.path.join(self.datadir, 'swamid-2.0-test.xml') self.swamid = root(parse_xml(self.swamid_source)) self.t = parse_xml(self.xml_source) self.non_metadata = parse_xml( resource_filename("not-metadata.xml", self.datadir)) def test_md_exists(self): assert (self.md is not None) def test_clone(self): entity_id = root(self.t).get('entityID') self.md.store.update(root(self.t), entity_id) nstore = deepcopy(self.md.store) assert (nstore.size() == self.md.store.size()) assert (nstore.lookup(entity_id) is not None) def test_sha1_hash(self): entity_id = root(self.t).get('entityID') self.md.store.update(root(self.t), entity_id) e = self.md.lookup(entity_id) assert (sha1_id( e[0]) == "{sha1}568515f6fae8c8b4d42d543853c96d08f051ef13") assert (hash_id( e[0], 'sha1', prefix=False) == "568515f6fae8c8b4d42d543853c96d08f051ef13") def test_entity_attribute(self): entity_id = root(self.t).get('entityID') set_entity_attributes(root(self.t), {"http://ns.example.org": "foo"}) self.md.store.update(root(self.t), entity_id) e = self.md.lookup("{%s}%s" % ("http://ns.example.org", 'foo'))[0] assert (e is not None) assert (e.get('entityID') == entity_id) def test_utils(self): entity_id = root(self.t).get('entityID') self.md.store.update(root(self.t), entity_id) e = self.md.lookup(entity_id)[0] assert (is_idp(e)) assert (not is_sp(e)) icon = entity_icon(e) assert ('url' in icon) assert ('https://www.example.com/static/images/umu_logo.jpg' in icon['url']) assert ('width' in icon) assert ('358' == icon['width']) assert ('height' in icon) assert ('63' == icon['height']) assert ('62' != icon['height']) domains = entity_domains(e) assert ('example.com' in domains) assert ('example.net' in domains) assert ('idp.example.com' not in domains) assert ('foo.com' not in domains) edup = deepcopy(e) name, desc = entity_extended_display(e) assert (name == 'Example University') assert (desc == 'Identity Provider for Example University') disp = entity_display_name(e) assert (disp == 'Example University') for elt in e.findall(".//{%s}DisplayName" % NS['mdui']): elt.getparent().remove(elt) disp = entity_display_name(e) assert (disp == 'The Example University') for elt in e.findall(".//{%s}OrganizationDisplayName" % NS['md']): elt.getparent().remove(elt) disp = entity_display_name(e) assert (disp == 'ExampleU') for elt in e.findall(".//{%s}OrganizationName" % NS['md']): elt.getparent().remove(elt) disp = entity_display_name(e) assert (disp == entity_id) e = edup subs = entity_domains(e) assert ('example.com' in subs) assert ('example.net' in subs) assert ('idp.example.com' not in subs) summary = entity_simple_summary(e) assert (summary['title'] == 'Example University') assert (summary['descr'] == 'Identity Provider for Example University') assert (summary['entityID'] == entity_id) assert ('entity_icon' in summary) assert ('icon_url' in summary and summary['entity_icon'] == summary['icon_url']) assert ('domains' in summary) assert ('id' in summary) empty = entity_simple_summary(None) assert (not empty) def test_display(self): swamid = root(self.swamid) self.md.store.update(swamid, swamid.get('Name')) funet_connect = self.md.lookup( 'https://connect.funet.fi/shibboleth')[0] name, desc = entity_extended_display(funet_connect) assert (name == 'FUNET E-Meeting Service') dn = entity_extended_display(funet_connect) def test_missing(self): swamid = root(self.swamid) self.md.store.update(swamid, swamid.get('Name')) missing = self.md.lookup('https://connect.funet.fi/shibboleth+missing') assert (len(missing) == 0) def test_non_metadata(self): e = root(self.non_metadata) assert metadata_expiration(e) is None try: annotate_entity(e, "kaka", "x", "y") set_entity_attributes(e, dict(a=1)) assert False except MetadataException: pass
class TestRepo(TestCase): def setUp(self): self.md = MDRepository(store=MemoryStore) self.datadir = resource_filename("metadata", "test/data") self.xml_source = os.path.join(self.datadir, "test01.xml") self.swamid_source = os.path.join(self.datadir, "swamid-2.0-test.xml") self.swamid = root(parse_xml(self.swamid_source)) self.t = parse_xml(self.xml_source) self.non_metadata = parse_xml(resource_filename("not-metadata.xml", self.datadir)) def test_md_exists(self): assert self.md is not None def test_clone(self): entity_id = root(self.t).get("entityID") self.md.store.update(root(self.t), entity_id) nmd = self.md.clone() assert nmd.store.size() == self.md.store.size() assert nmd.lookup(entity_id) is not None def test_sha1_hash(self): entity_id = root(self.t).get("entityID") self.md.store.update(root(self.t), entity_id) e = self.md.lookup(entity_id) assert self.md.sha1_id(e[0]) == "{sha1}568515f6fae8c8b4d42d543853c96d08f051ef13" assert hash_id(e[0], "sha1", prefix=False) == "568515f6fae8c8b4d42d543853c96d08f051ef13" def test_entity_attribute(self): entity_id = root(self.t).get("entityID") self.md.set_entity_attributes(root(self.t), {"http://ns.example.org": "foo"}) self.md.store.update(root(self.t), entity_id) e = self.md.lookup("{%s}%s" % ("http://ns.example.org", "foo"))[0] assert e is not None assert e.get("entityID") == entity_id def test_utils(self): entity_id = root(self.t).get("entityID") self.md.store.update(root(self.t), entity_id) e = self.md.lookup(entity_id)[0] assert self.md.is_idp(e) assert not self.md.is_sp(e) assert self.md.icon(e) in [ "https://www.example.com/static/images/logo.jpg", "https://www.example.com/static/images/logo_eng.jpg", ] domains = self.md.domains(e) assert "example.com" in domains assert "example.net" in domains assert "idp.example.com" in domains assert "foo.com" not in domains edup = deepcopy(e) name, desc = self.md.ext_display(e) assert name == "Example University" assert desc == "Identity Provider for Example University" disp = self.md.display(e) assert disp == "Example University" for elt in e.findall(".//{%s}DisplayName" % NS["mdui"]): elt.getparent().remove(elt) disp = self.md.display(e) assert disp == "The Example University" for elt in e.findall(".//{%s}OrganizationDisplayName" % NS["md"]): elt.getparent().remove(elt) disp = self.md.display(e) assert disp == "ExampleU" for elt in e.findall(".//{%s}OrganizationName" % NS["md"]): elt.getparent().remove(elt) disp = self.md.display(e) assert disp == entity_id e = edup subs = self.md.sub_domains(e) assert "example.com" in subs assert "example.net" in subs assert "idp.example.com" not in subs summary = self.md.simple_summary(e) assert summary["title"] == "Example University" assert summary["descr"] == "Identity Provider for Example University" assert summary["value"] == entity_id assert "icon" in summary assert "icon_url" in summary and summary["icon"] == summary["icon_url"] assert "domains" in summary assert "id" in summary empty = self.md.simple_summary(None) assert not empty def test_display(self): swamid = root(self.swamid) self.md.store.update(swamid, swamid.get("Name")) funet_connect = self.md.lookup("https://connect.funet.fi/shibboleth")[0] name, desc = self.md.ext_display(funet_connect) assert name == "FUNET E-Meeting Service" dn = self.md.display(funet_connect) def test_missing(self): swamid = root(self.swamid) self.md.store.update(swamid, swamid.get("Name")) missing = self.md.lookup("https://connect.funet.fi/shibboleth+missing") assert len(missing) == 0 def test_non_metadata(self): e = root(self.non_metadata) assert self.md.expiration(e) is None try: self.md.annotate(e, "kaka", "x", "y") self.md.set_entity_attributes(e, dict(a=1)) assert False except MetadataException: pass