Fixed metadata export/import to MongoDB store.
This commit is contained in:
@@ -79,6 +79,8 @@ def to_dict(_dict, onts, mdb_safe=False):
|
||||
for key, val in _dict.items():
|
||||
_val = _eval(val, onts, mdb_safe)
|
||||
if _val:
|
||||
if mdb_safe and "." in key:
|
||||
key = key.replace(".", "__")
|
||||
res[key] = _val
|
||||
return res
|
||||
|
||||
|
@@ -103,6 +103,9 @@ class MetaData(object):
|
||||
def keys(self):
|
||||
return self.entity.keys()
|
||||
|
||||
def values(self):
|
||||
return self.entity.keys()
|
||||
|
||||
def __contains__(self, item):
|
||||
return item in self.entity
|
||||
|
||||
|
@@ -246,6 +246,9 @@ class MDB(object):
|
||||
else:
|
||||
return True
|
||||
|
||||
def reset(self):
|
||||
self.db.drop()
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
class EptidMDB(Eptid):
|
||||
@@ -268,12 +271,60 @@ class EptidMDB(Eptid):
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
def export_mdstore_to_mongo_db(mds, onts, collection, sub_collection=""):
|
||||
|
||||
def protect(dic):
|
||||
res = {}
|
||||
for key, val in dic.items():
|
||||
key = key.replace(".", "__")
|
||||
if isinstance(val, basestring):
|
||||
pass
|
||||
elif isinstance(val, dict):
|
||||
val = protect(val)
|
||||
elif isinstance(val, list):
|
||||
li = []
|
||||
for va in val:
|
||||
if isinstance(va, basestring):
|
||||
pass
|
||||
elif isinstance(va, dict):
|
||||
va = protect(va)
|
||||
# I don't think lists of lists will appear am I wrong ?
|
||||
li.append(va)
|
||||
val = li
|
||||
res[key] = val
|
||||
return res
|
||||
|
||||
|
||||
def unprotect(dic):
|
||||
res = {}
|
||||
for key, val in dic.items():
|
||||
if key == "__class__":
|
||||
pass
|
||||
else:
|
||||
key = key.replace("__", ".")
|
||||
if isinstance(val, basestring):
|
||||
pass
|
||||
elif isinstance(val, dict):
|
||||
val = unprotect(val)
|
||||
elif isinstance(val, list):
|
||||
li = []
|
||||
for va in val:
|
||||
if isinstance(va, basestring):
|
||||
pass
|
||||
elif isinstance(val, dict):
|
||||
va = unprotect(va)
|
||||
li.append(va)
|
||||
val = li
|
||||
res[key] = val
|
||||
return res
|
||||
|
||||
|
||||
def export_mdstore_to_mongo_db(mds, collection, sub_collection=""):
|
||||
mdb = MDB(collection, sub_collection)
|
||||
mdb.reset()
|
||||
mdb.primary_key = "entity_id"
|
||||
for key, desc in mds.items():
|
||||
kwargs = {
|
||||
"entity_description": to_dict(desc, onts.values(), True),
|
||||
"entity_description": protect(desc),
|
||||
}
|
||||
mdb.store(key, **kwargs)
|
||||
|
||||
@@ -284,20 +335,6 @@ class MetadataMDB(MetaData):
|
||||
self.mdb = MDB(collection, sub_collection)
|
||||
self.mdb.primary_key = "entity_id"
|
||||
|
||||
def _service(self, entity_id, typ, service, binding=None):
|
||||
""" Get me all services with a specified
|
||||
entity ID and type, that supports the specified version of binding.
|
||||
|
||||
|
||||
:param entity_id: The EntityId
|
||||
:param typ: Type of service (idp, attribute_authority, ...)
|
||||
:param service: which service that is sought for
|
||||
:param binding: A binding identifier
|
||||
:return: list of service descriptions.
|
||||
Or if no binding was specified a list of 2-tuples (binding, srv)
|
||||
"""
|
||||
pass
|
||||
|
||||
def _ext_service(self, entity_id, typ, service, binding):
|
||||
try:
|
||||
srvs = self[entity_id][typ]
|
||||
@@ -322,11 +359,15 @@ class MetadataMDB(MetaData):
|
||||
|
||||
def items(self):
|
||||
for key, item in self.mdb.items():
|
||||
yield key, from_dict(item["entity_description"], self.onts, True)
|
||||
yield key, unprotect(item["entity_description"])
|
||||
|
||||
def keys(self):
|
||||
return self.mdb.keys()
|
||||
|
||||
def values(self):
|
||||
for key, item in self.mdb.items():
|
||||
yield unprotect(item["entity_description"])
|
||||
|
||||
def __contains__(self, item):
|
||||
return item in self.mdb
|
||||
|
||||
@@ -335,7 +376,7 @@ class MetadataMDB(MetaData):
|
||||
if not res:
|
||||
raise KeyError(item)
|
||||
elif len(res) == 1:
|
||||
return from_dict(res[0]["entity_description"], self.onts, True)
|
||||
return unprotect(res[0]["entity_description"])
|
||||
else:
|
||||
raise CorruptDatabase("More then one document with key %s" % item)
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
from saml2 import BINDING_HTTP_POST
|
||||
from saml2.mdstore import MetadataStore
|
||||
from saml2.saml import AUTHN_PASSWORD
|
||||
from saml2.client import Saml2Client
|
||||
from saml2.server import Server
|
||||
@@ -72,5 +73,7 @@ def test_eptid_mongo_db():
|
||||
assert e4 != e1
|
||||
assert e4 != e3
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_flow()
|
||||
|
82
tests/test_76_metadata_in_mdb.py
Normal file
82
tests/test_76_metadata_in_mdb.py
Normal file
@@ -0,0 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from saml2.mongo_store import export_mdstore_to_mongo_db, MetadataMDB
|
||||
from saml2.mdstore import MetadataStore, destinations, name
|
||||
|
||||
__author__ = 'rolandh'
|
||||
|
||||
from saml2.attribute_converter import d_to_local_name, ac_factory
|
||||
|
||||
from saml2 import saml
|
||||
from saml2 import md
|
||||
|
||||
from saml2.extension import mdui
|
||||
from saml2.extension import idpdisc
|
||||
from saml2.extension import dri
|
||||
from saml2.extension import mdattr
|
||||
from saml2.extension import ui
|
||||
import xmldsig
|
||||
import xmlenc
|
||||
|
||||
from pathutils import full_path, xmlsec_path
|
||||
|
||||
ONTS = {
|
||||
saml.NAMESPACE: saml,
|
||||
mdui.NAMESPACE: mdui,
|
||||
mdattr.NAMESPACE: mdattr,
|
||||
dri.NAMESPACE: dri,
|
||||
ui.NAMESPACE: ui,
|
||||
idpdisc.NAMESPACE: idpdisc,
|
||||
md.NAMESPACE: md,
|
||||
xmldsig.NAMESPACE: xmldsig,
|
||||
xmlenc.NAMESPACE: xmlenc
|
||||
}
|
||||
|
||||
ATTRCONV = ac_factory(full_path("attributemaps"))
|
||||
|
||||
|
||||
def _eq(l1, l2):
|
||||
return set(l1) == set(l2)
|
||||
|
||||
|
||||
def test_metadata():
|
||||
UMU_IDP = 'https://idp.umu.se/saml2/idp/metadata.php'
|
||||
mds = MetadataStore(ONTS.values(), ATTRCONV, xmlsec_path,
|
||||
disable_ssl_certificate_validation=True)
|
||||
|
||||
mds.imp({"local": [full_path("swamid-1.0.xml")]})
|
||||
assert len(mds) == 1 # One source
|
||||
|
||||
export_mdstore_to_mongo_db(mds, "metadata", "test")
|
||||
|
||||
mdmdb = MetadataMDB(ONTS, ATTRCONV, "metadata", "test")
|
||||
# replace all metadata instances with this one
|
||||
mds.metadata = {"mongo_db": mdmdb}
|
||||
|
||||
idps = mds.with_descriptor("idpsso")
|
||||
assert idps.keys()
|
||||
idpsso = mds.single_sign_on_service(UMU_IDP)
|
||||
assert len(idpsso) == 1
|
||||
assert destinations(idpsso) == [
|
||||
'https://idp.umu.se/saml2/idp/SSOService.php']
|
||||
|
||||
_name = name(mds[UMU_IDP])
|
||||
assert _name == u'Umeå University (SAML2)'
|
||||
certs = mds.certs(UMU_IDP, "idpsso", "signing")
|
||||
assert len(certs) == 1
|
||||
|
||||
sps = mds.with_descriptor("spsso")
|
||||
assert len(sps) == 108
|
||||
|
||||
wants = mds.attribute_requirement('https://connect8.sunet.se/shibboleth')
|
||||
lnamn = [d_to_local_name(mds.attrc, attr) for attr in wants["optional"]]
|
||||
assert _eq(lnamn, ['eduPersonPrincipalName', 'mail', 'givenName', 'sn',
|
||||
'eduPersonScopedAffiliation'])
|
||||
|
||||
wants = mds.attribute_requirement('https://beta.lobber.se/shibboleth')
|
||||
assert wants["required"] == []
|
||||
lnamn = [d_to_local_name(mds.attrc, attr) for attr in wants["optional"]]
|
||||
assert _eq(lnamn, ['eduPersonPrincipalName', 'mail', 'givenName', 'sn',
|
||||
'eduPersonScopedAffiliation', 'eduPersonEntitlement'])
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_metadata()
|
Reference in New Issue
Block a user