Basic tools that allows the metadata handling to be separated out from the IdP/SP/AA entity. Necessary when the size of the metadata files gets really big.

This commit is contained in:
Roland Hedberg 2012-12-15 10:45:22 +01:00
parent d6a470f83d
commit 5962a5a1c4
4 changed files with 237 additions and 149 deletions

136
src/saml2/mdie.py Normal file
View File

@ -0,0 +1,136 @@
__author__ = 'rolandh'
#!/usr/bin/env python
from saml2 import element_to_extension_element
from saml2 import extension_elements_to_elements
from saml2 import SamlBase
from saml2 import md
__author__ = 'rolandh'
"""
Functions used to import metadata from and export it to a pysaml2 format
"""
IMP_SKIP = ["_certs", "e_e_"]
EXP_SKIP = ["__class__"]
# From pysaml2 SAML2 metadata format to Python dictionary
def _eval(val, onts):
"""
Convert a value to a basic dict format
:param val: The value
:param onts: Schemas to be used in the conversion
:return: The basic dictionary
"""
if isinstance(val, basestring):
val = val.strip()
if not val:
return None
else:
return val
elif isinstance(val, dict) or isinstance(val, SamlBase):
return to_dict(val, onts)
elif isinstance(val, list):
lv = []
for v in val:
if isinstance(v, dict) or isinstance(v, SamlBase):
lv.append(to_dict(v, onts))
else:
lv.append(v)
return lv
return val
def to_dict(_dict, onts):
"""
Convert a pysaml2 SAML2 metadata format into a basic dictionary format
The export interface.
:param _dict: The pysaml2 metadata instance
:param onts: Schemas to use for the conversion
:return: The converted information
"""
res = {}
if isinstance(_dict, SamlBase):
res["__class__"] = "%s&%s" % (_dict.c_namespace,_dict.c_tag)
for key in _dict.keyswv():
if key in IMP_SKIP:
continue
val = getattr(_dict, key)
if key == "extension_elements":
_eel = extension_elements_to_elements(val, onts)
_val = [_eval(_v, onts) for _v in _eel]
else:
_val = _eval(val, onts)
if _val:
res[key] = _val
else:
for key, val in _dict.items():
_val = _eval(val, onts)
if _val:
res[key] = _val
return res
# From Python dictionary to pysaml2 SAML2 metadata format
def _kwa(val, onts):
"""
Key word argument conversion
:param val: A dictionary
:param onts: Schemas to use in the conversion
:return: A converted dictionary
"""
return dict([(k,_x(v, onts)) for k,v in val.items() if k not in EXP_SKIP])
def _x(val, onts):
"""
Converts a dictionary into a pysaml2 metadata object
:param val: A dictionary
:param onts: Schemas to use in the conversion
:return: The pysaml2 metadata object
"""
if isinstance(val, dict):
if "__class__" in val:
ns, typ = val["__class__"].split("&")
cls = getattr(onts[ns], typ)
if cls is md.Extensions:
lv = []
for key, ditems in val.items():
if key in EXP_SKIP:
continue
for item in ditems:
ns, typ = item["__class__"].split("&")
cls = getattr(onts[ns], typ)
kwargs = _kwa(item, onts)
inst = cls(**kwargs)
lv.append(element_to_extension_element(inst))
return lv
else:
kwargs = _kwa(val, onts)
inst = cls(**kwargs)
return inst
else:
res = {}
for key, v in val.items():
res[key] = _x(v, onts)
return res
elif isinstance(val, basestring):
return val
elif isinstance(val, list):
return [_x(v, onts) for v in val]
else:
return val
def from_dict(_dict, onts):
"""
Converts a dictionary into a pysaml2 metadata object.
The import interface.
:param val: A dictionary
:param onts: Schemas to use in the conversion
:return: The pysaml2 metadata object
"""
return dict([(key, _x(val, onts)) for key, val in _dict.items()])

View File

@ -1,149 +0,0 @@
#!/usr/bin/env python
from saml2 import metadata, element_to_extension_element
from saml2 import SamlBase
from saml2 import extension_elements_as_dict
from saml2 import saml
from saml2 import md
from saml2.attribute_converter import ac_factory
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
__author__ = 'rolandh'
"""
A script that imports and verifies metadata and stores it in a pysaml2 format
"""
MDIMPORT = {
"swamid": {
"url": "https://kalmar2.org/simplesaml/module.php/aggregator/?id=kalmarcentral2&set=saml2",
"cert":"kalmar2.pem"
},
# "incommon": {
# "url": "file://InCommon-metadata.xml"
# }
}
ATTRCONV = ac_factory("attributemaps")
def _eval(val):
if isinstance(val, basestring):
val = val.strip()
if not val:
return None
else:
return val
elif isinstance(val, dict) or isinstance(val, SamlBase):
return to_dict(val)
elif isinstance(val, list):
lv = []
for v in val:
if isinstance(v, dict) or isinstance(v, SamlBase):
lv.append(to_dict(v))
else:
lv.append(v)
return lv
return val
def to_dict(_dict):
res = {}
if isinstance(_dict, SamlBase):
res["__type__"] = "%s&%s" % (_dict.c_namespace,_dict.c_tag)
for key in _dict.keyswv():
val = getattr(_dict, key)
if key == "extension_elements":
_eed = extension_elements_as_dict(val, [idpdisc, mdui,
ui, dri, mdattr,
saml])
_val = {}
for key, _v in _eed.items():
_val[key] = _eval(_v)
else:
_val = _eval(val)
if _val:
res[key] = _val
else:
for key, val in _dict.items():
_val = _eval(val)
if _val:
res[key] = _val
return res
metad = metadata.MetaData(xmlsec_binary="/opt/local/bin/xmlsec1",
attrconv=ATTRCONV)
for key, spec in MDIMPORT.items():
url = spec["url"]
if url.startswith("file://"):
metad.import_metadata(open(url[7:]).read(),key)
else:
metad.import_external_metadata(url, spec["cert"])
_dict = to_dict(metad.entity)
#print _dict
SKIP = ["__type__", "_certs"]
def _kwa(val, onts):
return dict([(k,_x(v, onts)) for k,v in val.items() if k not in SKIP])
def _x(val, onts):
if isinstance(val, dict):
if "__type__" in val:
ns, typ = val["__type__"].split("&")
cls = getattr(onts[ns], typ)
if cls is md.Extensions:
lv = []
for key, ditems in val.items():
if key in SKIP:
continue
for _k, items in ditems.items():
for item in items:
ns, typ = item["__type__"].split("&")
cls = getattr(onts[ns], typ)
kwargs = _kwa(item, onts)
inst = cls(**kwargs)
lv.append(element_to_extension_element(inst))
return lv
else:
kwargs = _kwa(val, onts)
inst = cls(**kwargs)
return inst
else:
res = {}
for key, v in val.items():
res[key] = _x(v, onts)
return res
elif isinstance(val, basestring):
return val
elif isinstance(val, list):
return [_x(v, onts) for v in val]
else:
return val
def from_dict(_dict, onts):
res = {}
for key, val in _dict.items():
res[key] = _x(val, onts)
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
}
res = from_dict(_dict, ONTS)
print res[res.keys()[0]]

68
tools/mdexport.py Executable file
View File

@ -0,0 +1,68 @@
#!/usr/bin/env python
import sys
from saml2 import metadata
from saml2 import saml
from saml2 import md
from saml2.attribute_converter import ac_factory
from saml2.mdie import to_dict
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
__author__ = 'rolandh'
"""
A script that imports and verifies metadata and dumps it in a basic
dictionary format.
"""
MDIMPORT = {
"swamid": {
"url": "https://kalmar2.org/simplesaml/module.php/aggregator/?id=kalmarcentral2&set=saml2",
"cert":"kalmar2.pem"
},
"incommon": {
"url": "file://InCommon-metadata.xml"
},
"test": {
"url": "file://mdtest.xml"
}
}
ATTRCONV = ac_factory("attributemaps")
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
}
metad = metadata.MetaData(xmlsec_binary="/opt/local/bin/xmlsec1",
attrconv=ATTRCONV)
for src in sys.argv[1:]:
spec = MDIMPORT[src]
url = spec["url"]
if url.startswith("file://"):
metad.import_metadata(open(url[7:]).read(), src)
else:
metad.import_external_metadata(url, spec["cert"])
_dict = to_dict(metad.entity, ONTS.values())
import json
print json.dumps(_dict, indent=2)

33
tools/mdimport.py Executable file
View File

@ -0,0 +1,33 @@
#!/usr/bin/env python
import sys
__author__ = 'rolandh'
from saml2.mdie import from_dict
import xmldsig
import xmlenc
from saml2 import md
from saml2 import saml
from saml2.extension import dri
from saml2.extension import idpdisc
from saml2.extension import mdattr
from saml2.extension import mdui
from saml2.extension import ui
ONTS = {
dri.NAMESPACE: dri,
idpdisc.NAMESPACE: idpdisc,
md.NAMESPACE: md,
mdattr.NAMESPACE: mdattr,
mdui.NAMESPACE: mdui,
saml.NAMESPACE: saml,
ui.NAMESPACE: ui,
xmlenc.NAMESPACE: xmlenc,
xmldsig.NAMESPACE: xmldsig,
}
_dict = eval(open(sys.argv[1]).read())
res = from_dict(_dict, ONTS)
print res