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():
|
for key, val in _dict.items():
|
||||||
_val = _eval(val, onts, mdb_safe)
|
_val = _eval(val, onts, mdb_safe)
|
||||||
if _val:
|
if _val:
|
||||||
|
if mdb_safe and "." in key:
|
||||||
|
key = key.replace(".", "__")
|
||||||
res[key] = _val
|
res[key] = _val
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@@ -103,6 +103,9 @@ class MetaData(object):
|
|||||||
def keys(self):
|
def keys(self):
|
||||||
return self.entity.keys()
|
return self.entity.keys()
|
||||||
|
|
||||||
|
def values(self):
|
||||||
|
return self.entity.keys()
|
||||||
|
|
||||||
def __contains__(self, item):
|
def __contains__(self, item):
|
||||||
return item in self.entity
|
return item in self.entity
|
||||||
|
|
||||||
|
@@ -246,6 +246,9 @@ class MDB(object):
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.db.drop()
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
class EptidMDB(Eptid):
|
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 = MDB(collection, sub_collection)
|
||||||
|
mdb.reset()
|
||||||
mdb.primary_key = "entity_id"
|
mdb.primary_key = "entity_id"
|
||||||
for key, desc in mds.items():
|
for key, desc in mds.items():
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"entity_description": to_dict(desc, onts.values(), True),
|
"entity_description": protect(desc),
|
||||||
}
|
}
|
||||||
mdb.store(key, **kwargs)
|
mdb.store(key, **kwargs)
|
||||||
|
|
||||||
@@ -284,20 +335,6 @@ class MetadataMDB(MetaData):
|
|||||||
self.mdb = MDB(collection, sub_collection)
|
self.mdb = MDB(collection, sub_collection)
|
||||||
self.mdb.primary_key = "entity_id"
|
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):
|
def _ext_service(self, entity_id, typ, service, binding):
|
||||||
try:
|
try:
|
||||||
srvs = self[entity_id][typ]
|
srvs = self[entity_id][typ]
|
||||||
@@ -322,11 +359,15 @@ class MetadataMDB(MetaData):
|
|||||||
|
|
||||||
def items(self):
|
def items(self):
|
||||||
for key, item in self.mdb.items():
|
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):
|
def keys(self):
|
||||||
return self.mdb.keys()
|
return self.mdb.keys()
|
||||||
|
|
||||||
|
def values(self):
|
||||||
|
for key, item in self.mdb.items():
|
||||||
|
yield unprotect(item["entity_description"])
|
||||||
|
|
||||||
def __contains__(self, item):
|
def __contains__(self, item):
|
||||||
return item in self.mdb
|
return item in self.mdb
|
||||||
|
|
||||||
@@ -335,7 +376,7 @@ class MetadataMDB(MetaData):
|
|||||||
if not res:
|
if not res:
|
||||||
raise KeyError(item)
|
raise KeyError(item)
|
||||||
elif len(res) == 1:
|
elif len(res) == 1:
|
||||||
return from_dict(res[0]["entity_description"], self.onts, True)
|
return unprotect(res[0]["entity_description"])
|
||||||
else:
|
else:
|
||||||
raise CorruptDatabase("More then one document with key %s" % item)
|
raise CorruptDatabase("More then one document with key %s" % item)
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
from saml2 import BINDING_HTTP_POST
|
from saml2 import BINDING_HTTP_POST
|
||||||
|
from saml2.mdstore import MetadataStore
|
||||||
from saml2.saml import AUTHN_PASSWORD
|
from saml2.saml import AUTHN_PASSWORD
|
||||||
from saml2.client import Saml2Client
|
from saml2.client import Saml2Client
|
||||||
from saml2.server import Server
|
from saml2.server import Server
|
||||||
@@ -72,5 +73,7 @@ def test_eptid_mongo_db():
|
|||||||
assert e4 != e1
|
assert e4 != e1
|
||||||
assert e4 != e3
|
assert e4 != e3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_flow()
|
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