Fixed metadata export/import to MongoDB store.

This commit is contained in:
Roland Hedberg
2013-04-19 18:09:04 +02:00
parent 287793da79
commit c0d9144172
5 changed files with 149 additions and 18 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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()

View 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()