Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Hans Hörberg
2014-03-18 10:39:44 +01:00
24 changed files with 623 additions and 307 deletions

View File

@@ -45,9 +45,9 @@ copyright = u'2010-2011, Roland Hedberg'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '0.4' version = '1.2'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.4.2' release = '1.2.0beta'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View File

@@ -10,8 +10,8 @@ Install PySAML2
--------------- ---------------
For all this to work you need to have Python installed. For all this to work you need to have Python installed.
The development has been done using 2.6. The development has been done using 2.7.
There is no 3.X version yet. There is now a 3.X version.
Prerequisites Prerequisites
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
@@ -21,19 +21,17 @@ if it's recent enough, or if the Python is too old you have to install it,
for instance by getting it from the Python Package Instance by using for instance by getting it from the Python Package Instance by using
easy_install. easy_install.
You also need xmlsec which you can download from http://www.aleksey.com/xmlsec/ You also need xmlsec1 which you can download from http://www.aleksey.com/xmlsec/
If you're on OS X you can get xmlsec installed from MacPorts or Fink. If you're on OS X you can get xmlsec1 installed from MacPorts or Fink.
Depending on how you are going to use PySAML2 you might also need Depending on how you are going to use PySAML2 you might also need
* Mako * Mako
* pyASN1 * pyASN1
* repoze.who (make sure you get 1.0.16 and not 2.0) * repoze.who
* decorator
* python-memcache * python-memcache
* memcached * memcached
* M2Crypto
Quick build instructions Quick build instructions
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,6 +42,10 @@ Once you have installed all the necessary prerequisites a simple::
will install the basic code. will install the basic code.
Note for rhel/centos 6: cffi depends on libffi-devel, and cryptography on openssl-devel to compile
So you might want first to do:
yum install libffi-devel openssl-devel
After this you ought to be able to run the tests without an hitch. After this you ought to be able to run the tests without an hitch.
The tests are based on the pypy test environment, so:: The tests are based on the pypy test environment, so::

View File

@@ -45,7 +45,8 @@ install_requires = [
'repoze.who', 'repoze.who',
'pycrypto', # 'Crypto' 'pycrypto', # 'Crypto'
'pytz', 'pytz',
'pyOpenSSL' 'pyOpenSSL',
'python-dateutil'
] ]
tests_require = [ tests_require = [

View File

@@ -444,13 +444,12 @@ class SamlBase(ExtensionContainer):
c_children = {} c_children = {}
c_attributes = {} c_attributes = {}
c_attribute_type = {} c_attribute_type = {}
#c_attribute_use = {}
#c_attribute_required = {}
c_child_order = [] c_child_order = []
c_cardinality = {} c_cardinality = {}
c_any = None c_any = None
c_any_attribute = None c_any_attribute = None
c_value_type = None c_value_type = None
c_ns_prefix = None
def _get_all_c_children_with_order(self): def _get_all_c_children_with_order(self):
if len(self.c_child_order) > 0: if len(self.c_child_order) > 0:
@@ -549,6 +548,9 @@ class SamlBase(ExtensionContainer):
constructing the text representation. constructing the text representation.
:return: String representation of the object :return: String representation of the object
""" """
if not nspair and self.c_ns_prefix:
nspair = self.c_ns_prefix
if nspair: if nspair:
for prefix, uri in nspair.items(): for prefix, uri in nspair.items():
try: try:

View File

@@ -7,7 +7,7 @@ NETSCAPE_LDAP = "urn:oid:2.16.840.1.113730.3.1."
UCL_DIR_PILOT = 'urn:oid:0.9.2342.19200300.100.1.' UCL_DIR_PILOT = 'urn:oid:0.9.2342.19200300.100.1.'
PKCS_9 = "urn:oid:1.2.840.113549.1.9.1." PKCS_9 = "urn:oid:1.2.840.113549.1.9.1."
UMICH = "urn:oid:1.3.6.1.4.1.250.1.57." UMICH = "urn:oid:1.3.6.1.4.1.250.1.57."
SCHAC = "urn:oid:1.3.6.1.4.1.25178.2." SCHAC = "urn:oid:1.3.6.1.4.1.25178.1.2."
#urn:oid:1.3.6.1.4.1.1466.115.121.1.26 #urn:oid:1.3.6.1.4.1.1466.115.121.1.26

View File

@@ -254,12 +254,6 @@ class Saml2Client(Base):
status["reason"], status["not_on_or_after"], status["reason"], status["not_on_or_after"],
status["sign"]) status["sign"])
# ========================================================================
# MUST use SOAP for
# AssertionIDRequest, SubjectQuery, AuthnQuery, AttributeQuery or
# AuthzDecisionQuery
# ========================================================================
def _use_soap(self, destination, query_type, **kwargs): def _use_soap(self, destination, query_type, **kwargs):
_create_func = getattr(self, "create_%s" % query_type) _create_func = getattr(self, "create_%s" % query_type)
_response_func = getattr(self, "parse_%s_response" % query_type) _response_func = getattr(self, "parse_%s_response" % query_type)
@@ -432,13 +426,14 @@ class Saml2Client(Base):
:param sign: Whether the response will be signed or not :param sign: Whether the response will be signed or not
:return: Keyword arguments which can be used to send the response :return: Keyword arguments which can be used to send the response
what's returned follow different patterns for different bindings. what's returned follow different patterns for different bindings.
If the binding is BINDIND_SOAP, what is returned looks like this: If the binding is BINDIND_SOAP, what is returned looks like this::
{
"data": <the SOAP enveloped response> {
"url": "", "data": <the SOAP enveloped response>
'headers': [('content-type', 'application/soap+xml')] "url": "",
'method': "POST 'headers': [('content-type', 'application/soap+xml')]
} 'method': "POST
}
""" """
logger.info("logout request: %s" % request) logger.info("logout request: %s" % request)

View File

@@ -70,7 +70,8 @@ COMMON_ARGS = [
"verify_encrypt_cert", "verify_encrypt_cert",
"tmp_cert_file", "tmp_cert_file",
"tmp_key_file", "tmp_key_file",
"validate_certificate" "validate_certificate",
"extensions"
] ]
SP_ARGS = [ SP_ARGS = [
@@ -219,6 +220,7 @@ class Config(object):
self.tmp_cert_file = None self.tmp_cert_file = None
self.tmp_key_file = None self.tmp_key_file = None
self.validate_certificate = None self.validate_certificate = None
self.extensions = {}
def setattr(self, context, attr, val): def setattr(self, context, attr, val):
if context == "": if context == "":
@@ -337,6 +339,9 @@ class Config(object):
except KeyError: except KeyError:
pass pass
if "extensions" in cnf:
self.do_extensions(cnf["extensions"])
self.load_complex(cnf, metadata_construction=metadata_construction) self.load_complex(cnf, metadata_construction=metadata_construction)
self.context = self.def_context self.context = self.def_context
@@ -480,6 +485,11 @@ class Config(object):
return None, None return None, None
def do_extensions(self, extensions):
for key, val in extensions.items():
self.extensions[key] = val
class SPConfig(Config): class SPConfig(Config):
def_context = "sp" def_context = "sp"

View File

@@ -1,10 +1,11 @@
__author__ = 'rolandh' __author__ = 'rolandh'
INC = "http://id.incommon.org/category/research-and-scholarship" RESEARCH_AND_SCHOLARSHIP = "http://id.incommon.org/category/research-and-scholarship"
RELEASE = { RELEASE = {
"": ["eduPersonTargetedID"], "": ["eduPersonTargetedID"],
INC: ["eduPersonPrincipalName", "eduPersonScopedAffiliation", "mail", RESEARCH_AND_SCHOLARSHIP: ["eduPersonPrincipalName",
"givenName", "sn", "displayName"] "eduPersonScopedAffiliation", "mail",
"givenName", "sn", "displayName"]
} }

View File

@@ -0,0 +1,11 @@
__author__ = 'rolandh'
RESEARCH_AND_SCHOLARSHIP = "http://refeds.org/category/research-and-scholarship"
RELEASE = {
"": ["eduPersonTargetedID"],
RESEARCH_AND_SCHOLARSHIP: ["eduPersonPrincipalName",
"eduPersonScopedAffiliation", "mail",
"givenName", "sn", "displayName"]
}

View File

@@ -2,7 +2,7 @@ __author__ = 'rolandh'
NAME = ["givenName", "displayName", "sn"] NAME = ["givenName", "displayName", "sn"]
STATIC_ORG_INFO = ["c", "o", "co"] STATIC_ORG_INFO = ["c", "o", "co", "norEduOrgAcronym", "schacHomeOrganization"]
OTHER = ["eduPersonPrincipalName", "eduPersonScopedAffiliation", "mail"] OTHER = ["eduPersonPrincipalName", "eduPersonScopedAffiliation", "mail"]
# These give you access to information # These give you access to information

View File

@@ -11,6 +11,7 @@ from saml2 import md
NAMESPACE = 'urn:oasis:names:tc:SAML:metadata:rpi' NAMESPACE = 'urn:oasis:names:tc:SAML:metadata:rpi'
class RegistrationPolicy(md.LocalizedURIType_): class RegistrationPolicy(md.LocalizedURIType_):
"""The urn:oasis:names:tc:SAML:metadata:rpi:RegistrationPolicy element """ """The urn:oasis:names:tc:SAML:metadata:rpi:RegistrationPolicy element """
@@ -21,6 +22,7 @@ class RegistrationPolicy(md.LocalizedURIType_):
c_child_order = md.LocalizedURIType_.c_child_order[:] c_child_order = md.LocalizedURIType_.c_child_order[:]
c_cardinality = md.LocalizedURIType_.c_cardinality.copy() c_cardinality = md.LocalizedURIType_.c_cardinality.copy()
def registration_policy_from_string(xml_string): def registration_policy_from_string(xml_string):
return saml2.create_class_from_xml_string(RegistrationPolicy, xml_string) return saml2.create_class_from_xml_string(RegistrationPolicy, xml_string)
@@ -35,6 +37,7 @@ class UsagePolicy(md.LocalizedURIType_):
c_child_order = md.LocalizedURIType_.c_child_order[:] c_child_order = md.LocalizedURIType_.c_child_order[:]
c_cardinality = md.LocalizedURIType_.c_cardinality.copy() c_cardinality = md.LocalizedURIType_.c_cardinality.copy()
def usage_policy_from_string(xml_string): def usage_policy_from_string(xml_string):
return saml2.create_class_from_xml_string(UsagePolicy, xml_string) return saml2.create_class_from_xml_string(UsagePolicy, xml_string)
@@ -53,21 +56,20 @@ class PublicationType_(SamlBase):
c_attributes['publicationId'] = ('publication_id', 'string', False) c_attributes['publicationId'] = ('publication_id', 'string', False)
def __init__(self, def __init__(self,
publisher=None, publisher=None,
creation_instant=None, creation_instant=None,
publication_id=None, publication_id=None,
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None extension_attributes=None):
):
SamlBase.__init__(self, SamlBase.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.publisher = publisher
self.publisher=publisher self.creation_instant = creation_instant
self.creation_instant=creation_instant self.publication_id = publication_id
self.publication_id=publication_id
def publication_type__from_string(xml_string): def publication_type__from_string(xml_string):
return saml2.create_class_from_xml_string(PublicationType_, xml_string) return saml2.create_class_from_xml_string(PublicationType_, xml_string)
@@ -82,28 +84,30 @@ class RegistrationInfoType_(SamlBase):
c_attributes = SamlBase.c_attributes.copy() c_attributes = SamlBase.c_attributes.copy()
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
c_children['{urn:oasis:names:tc:SAML:metadata:rpi}RegistrationPolicy'] = ('registration_policy', [RegistrationPolicy]) c_children['{urn:oasis:names:tc:SAML:metadata:rpi}RegistrationPolicy'] = (
c_cardinality['registration_policy'] = {"min":0} 'registration_policy', [RegistrationPolicy])
c_attributes['registrationAuthority'] = ('registration_authority', 'string', True) c_cardinality['registration_policy'] = {"min": 0}
c_attributes['registrationInstant'] = ('registration_instant', 'dateTime', False) c_attributes['registrationAuthority'] = (
'registration_authority', 'string', True)
c_attributes['registrationInstant'] = (
'registration_instant', 'dateTime', False)
c_child_order.extend(['registration_policy']) c_child_order.extend(['registration_policy'])
def __init__(self, def __init__(self,
registration_policy=None, registration_policy=None,
registration_authority=None, registration_authority=None,
registration_instant=None, registration_instant=None,
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None extension_attributes=None):
):
SamlBase.__init__(self, SamlBase.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.registration_policy = registration_policy or []
self.registration_policy=registration_policy or [] self.registration_authority = registration_authority
self.registration_authority=registration_authority self.registration_instant = registration_instant
self.registration_instant=registration_instant
def registration_info_type__from_string(xml_string): def registration_info_type__from_string(xml_string):
return saml2.create_class_from_xml_string(RegistrationInfoType_, xml_string) return saml2.create_class_from_xml_string(RegistrationInfoType_, xml_string)
@@ -118,31 +122,31 @@ class PublicationInfoType_(SamlBase):
c_attributes = SamlBase.c_attributes.copy() c_attributes = SamlBase.c_attributes.copy()
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
c_children['{urn:oasis:names:tc:SAML:metadata:rpi}UsagePolicy'] = ('usage_policy', [UsagePolicy]) c_children['{urn:oasis:names:tc:SAML:metadata:rpi}UsagePolicy'] = (
c_cardinality['usage_policy'] = {"min":0} 'usage_policy', [UsagePolicy])
c_cardinality['usage_policy'] = {"min": 0}
c_attributes['publisher'] = ('publisher', 'string', True) c_attributes['publisher'] = ('publisher', 'string', True)
c_attributes['creationInstant'] = ('creation_instant', 'dateTime', False) c_attributes['creationInstant'] = ('creation_instant', 'dateTime', False)
c_attributes['publicationId'] = ('publication_id', 'string', False) c_attributes['publicationId'] = ('publication_id', 'string', False)
c_child_order.extend(['usage_policy']) c_child_order.extend(['usage_policy'])
def __init__(self, def __init__(self,
usage_policy=None, usage_policy=None,
publisher=None, publisher=None,
creation_instant=None, creation_instant=None,
publication_id=None, publication_id=None,
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None extension_attributes=None):
):
SamlBase.__init__(self, SamlBase.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.usage_policy = usage_policy or []
self.usage_policy=usage_policy or [] self.publisher = publisher
self.publisher=publisher self.creation_instant = creation_instant
self.creation_instant=creation_instant self.publication_id = publication_id
self.publication_id=publication_id
def publication_info_type__from_string(xml_string): def publication_info_type__from_string(xml_string):
return saml2.create_class_from_xml_string(PublicationInfoType_, xml_string) return saml2.create_class_from_xml_string(PublicationInfoType_, xml_string)
@@ -158,6 +162,7 @@ class Publication(PublicationType_):
c_child_order = PublicationType_.c_child_order[:] c_child_order = PublicationType_.c_child_order[:]
c_cardinality = PublicationType_.c_cardinality.copy() c_cardinality = PublicationType_.c_cardinality.copy()
def publication_from_string(xml_string): def publication_from_string(xml_string):
return saml2.create_class_from_xml_string(Publication, xml_string) return saml2.create_class_from_xml_string(Publication, xml_string)
@@ -172,6 +177,7 @@ class RegistrationInfo(RegistrationInfoType_):
c_child_order = RegistrationInfoType_.c_child_order[:] c_child_order = RegistrationInfoType_.c_child_order[:]
c_cardinality = RegistrationInfoType_.c_cardinality.copy() c_cardinality = RegistrationInfoType_.c_cardinality.copy()
def registration_info_from_string(xml_string): def registration_info_from_string(xml_string):
return saml2.create_class_from_xml_string(RegistrationInfo, xml_string) return saml2.create_class_from_xml_string(RegistrationInfo, xml_string)
@@ -186,6 +192,7 @@ class PublicationInfo(PublicationInfoType_):
c_child_order = PublicationInfoType_.c_child_order[:] c_child_order = PublicationInfoType_.c_child_order[:]
c_cardinality = PublicationInfoType_.c_cardinality.copy() c_cardinality = PublicationInfoType_.c_cardinality.copy()
def publication_info_from_string(xml_string): def publication_info_from_string(xml_string):
return saml2.create_class_from_xml_string(PublicationInfo, xml_string) return saml2.create_class_from_xml_string(PublicationInfo, xml_string)
@@ -199,22 +206,22 @@ class PublicationPathType_(SamlBase):
c_attributes = SamlBase.c_attributes.copy() c_attributes = SamlBase.c_attributes.copy()
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
c_children['{urn:oasis:names:tc:SAML:metadata:rpi}Publication'] = ('publication', [Publication]) c_children['{urn:oasis:names:tc:SAML:metadata:rpi}Publication'] = (
c_cardinality['publication'] = {"min":0} 'publication', [Publication])
c_cardinality['publication'] = {"min": 0}
c_child_order.extend(['publication']) c_child_order.extend(['publication'])
def __init__(self, def __init__(self,
publication=None, publication=None,
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None extension_attributes=None):
):
SamlBase.__init__(self, SamlBase.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.publication = publication or []
self.publication=publication or []
def publication_path_type__from_string(xml_string): def publication_path_type__from_string(xml_string):
return saml2.create_class_from_xml_string(PublicationPathType_, xml_string) return saml2.create_class_from_xml_string(PublicationPathType_, xml_string)
@@ -230,6 +237,7 @@ class PublicationPath(PublicationPathType_):
c_child_order = PublicationPathType_.c_child_order[:] c_child_order = PublicationPathType_.c_child_order[:]
c_cardinality = PublicationPathType_.c_cardinality.copy() c_cardinality = PublicationPathType_.c_cardinality.copy()
def publication_path_from_string(xml_string): def publication_path_from_string(xml_string):
return saml2.create_class_from_xml_string(PublicationPath, xml_string) return saml2.create_class_from_xml_string(PublicationPath, xml_string)

View File

@@ -11,6 +11,7 @@ from saml2 import md
NAMESPACE = 'urn:oasis:names:tc:SAML:metadata:ui' NAMESPACE = 'urn:oasis:names:tc:SAML:metadata:ui'
class DisplayName(md.LocalizedNameType_): class DisplayName(md.LocalizedNameType_):
"""The urn:oasis:names:tc:SAML:metadata:ui:DisplayName element """ """The urn:oasis:names:tc:SAML:metadata:ui:DisplayName element """
@@ -21,6 +22,7 @@ class DisplayName(md.LocalizedNameType_):
c_child_order = md.LocalizedNameType_.c_child_order[:] c_child_order = md.LocalizedNameType_.c_child_order[:]
c_cardinality = md.LocalizedNameType_.c_cardinality.copy() c_cardinality = md.LocalizedNameType_.c_cardinality.copy()
def display_name_from_string(xml_string): def display_name_from_string(xml_string):
return saml2.create_class_from_xml_string(DisplayName, xml_string) return saml2.create_class_from_xml_string(DisplayName, xml_string)
@@ -35,6 +37,7 @@ class Description(md.LocalizedNameType_):
c_child_order = md.LocalizedNameType_.c_child_order[:] c_child_order = md.LocalizedNameType_.c_child_order[:]
c_cardinality = md.LocalizedNameType_.c_cardinality.copy() c_cardinality = md.LocalizedNameType_.c_cardinality.copy()
def description_from_string(xml_string): def description_from_string(xml_string):
return saml2.create_class_from_xml_string(Description, xml_string) return saml2.create_class_from_xml_string(Description, xml_string)
@@ -49,6 +52,7 @@ class InformationURL(md.LocalizedURIType_):
c_child_order = md.LocalizedURIType_.c_child_order[:] c_child_order = md.LocalizedURIType_.c_child_order[:]
c_cardinality = md.LocalizedURIType_.c_cardinality.copy() c_cardinality = md.LocalizedURIType_.c_cardinality.copy()
def information_url_from_string(xml_string): def information_url_from_string(xml_string):
return saml2.create_class_from_xml_string(InformationURL, xml_string) return saml2.create_class_from_xml_string(InformationURL, xml_string)
@@ -63,6 +67,7 @@ class PrivacyStatementURL(md.LocalizedURIType_):
c_child_order = md.LocalizedURIType_.c_child_order[:] c_child_order = md.LocalizedURIType_.c_child_order[:]
c_cardinality = md.LocalizedURIType_.c_cardinality.copy() c_cardinality = md.LocalizedURIType_.c_cardinality.copy()
def privacy_statement_url_from_string(xml_string): def privacy_statement_url_from_string(xml_string):
return saml2.create_class_from_xml_string(PrivacyStatementURL, xml_string) return saml2.create_class_from_xml_string(PrivacyStatementURL, xml_string)
@@ -78,6 +83,7 @@ class ListOfStrings_(SamlBase):
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
def list_of_strings__from_string(xml_string): def list_of_strings__from_string(xml_string):
return saml2.create_class_from_xml_string(ListOfStrings_, xml_string) return saml2.create_class_from_xml_string(ListOfStrings_, xml_string)
@@ -91,20 +97,20 @@ class KeywordsType_(ListOfStrings_):
c_attributes = ListOfStrings_.c_attributes.copy() c_attributes = ListOfStrings_.c_attributes.copy()
c_child_order = ListOfStrings_.c_child_order[:] c_child_order = ListOfStrings_.c_child_order[:]
c_cardinality = ListOfStrings_.c_cardinality.copy() c_cardinality = ListOfStrings_.c_cardinality.copy()
c_attributes['{http://www.w3.org/XML/1998/namespace}lang'] = ('lang', 'mdui:listOfStrings', True) c_attributes['{http://www.w3.org/XML/1998/namespace}lang'] = (
'lang', 'mdui:listOfStrings', True)
def __init__(self, def __init__(self,
lang=None, lang=None,
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None, extension_attributes=None):
):
ListOfStrings_.__init__(self, ListOfStrings_.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.lang = lang
self.lang=lang
def keywords_type__from_string(xml_string): def keywords_type__from_string(xml_string):
return saml2.create_class_from_xml_string(KeywordsType_, xml_string) return saml2.create_class_from_xml_string(KeywordsType_, xml_string)
@@ -122,24 +128,24 @@ class LogoType_(SamlBase):
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
c_attributes['height'] = ('height', 'positiveInteger', True) c_attributes['height'] = ('height', 'positiveInteger', True)
c_attributes['width'] = ('width', 'positiveInteger', True) c_attributes['width'] = ('width', 'positiveInteger', True)
c_attributes['{http://www.w3.org/XML/1998/namespace}lang'] = ('lang', 'anyURI', False) c_attributes['{http://www.w3.org/XML/1998/namespace}lang'] = (
'lang', 'anyURI', False)
def __init__(self, def __init__(self,
height=None, height=None,
width=None, width=None,
lang=None, lang=None,
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None, extension_attributes=None):
):
SamlBase.__init__(self, SamlBase.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.height = height
self.height=height self.width = width
self.width=width self.lang = lang
self.lang=lang
def logo_type__from_string(xml_string): def logo_type__from_string(xml_string):
return saml2.create_class_from_xml_string(LogoType_, xml_string) return saml2.create_class_from_xml_string(LogoType_, xml_string)
@@ -156,6 +162,7 @@ class IPHint(SamlBase):
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
def ip_hint_from_string(xml_string): def ip_hint_from_string(xml_string):
return saml2.create_class_from_xml_string(IPHint, xml_string) return saml2.create_class_from_xml_string(IPHint, xml_string)
@@ -171,6 +178,7 @@ class DomainHint(SamlBase):
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
def domain_hint_from_string(xml_string): def domain_hint_from_string(xml_string):
return saml2.create_class_from_xml_string(DomainHint, xml_string) return saml2.create_class_from_xml_string(DomainHint, xml_string)
@@ -186,6 +194,7 @@ class GeolocationHint(SamlBase):
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
def geolocation_hint_from_string(xml_string): def geolocation_hint_from_string(xml_string):
return saml2.create_class_from_xml_string(GeolocationHint, xml_string) return saml2.create_class_from_xml_string(GeolocationHint, xml_string)
@@ -200,6 +209,7 @@ class Keywords(KeywordsType_):
c_child_order = KeywordsType_.c_child_order[:] c_child_order = KeywordsType_.c_child_order[:]
c_cardinality = KeywordsType_.c_cardinality.copy() c_cardinality = KeywordsType_.c_cardinality.copy()
def keywords_from_string(xml_string): def keywords_from_string(xml_string):
return saml2.create_class_from_xml_string(Keywords, xml_string) return saml2.create_class_from_xml_string(Keywords, xml_string)
@@ -214,6 +224,7 @@ class Logo(LogoType_):
c_child_order = LogoType_.c_child_order[:] c_child_order = LogoType_.c_child_order[:]
c_cardinality = LogoType_.c_cardinality.copy() c_cardinality = LogoType_.c_cardinality.copy()
def logo_from_string(xml_string): def logo_from_string(xml_string):
return saml2.create_class_from_xml_string(Logo, xml_string) return saml2.create_class_from_xml_string(Logo, xml_string)
@@ -227,30 +238,32 @@ class DiscoHintsType_(SamlBase):
c_attributes = SamlBase.c_attributes.copy() c_attributes = SamlBase.c_attributes.copy()
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
c_children['{urn:oasis:names:tc:SAML:metadata:ui}IPHint'] = ('ip_hint', [IPHint]) c_children['{urn:oasis:names:tc:SAML:metadata:ui}IPHint'] = (
c_cardinality['ip_hint'] = {"min":0} 'ip_hint', [IPHint])
c_children['{urn:oasis:names:tc:SAML:metadata:ui}DomainHint'] = ('domain_hint', [DomainHint]) c_cardinality['ip_hint'] = {"min": 0}
c_cardinality['domain_hint'] = {"min":0} c_children['{urn:oasis:names:tc:SAML:metadata:ui}DomainHint'] = (
c_children['{urn:oasis:names:tc:SAML:metadata:ui}GeolocationHint'] = ('geolocation_hint', [GeolocationHint]) 'domain_hint', [DomainHint])
c_cardinality['geolocation_hint'] = {"min":0} c_cardinality['domain_hint'] = {"min": 0}
c_children['{urn:oasis:names:tc:SAML:metadata:ui}GeolocationHint'] = (
'geolocation_hint', [GeolocationHint])
c_cardinality['geolocation_hint'] = {"min": 0}
c_child_order.extend(['ip_hint', 'domain_hint', 'geolocation_hint']) c_child_order.extend(['ip_hint', 'domain_hint', 'geolocation_hint'])
def __init__(self, def __init__(self,
ip_hint=None, ip_hint=None,
domain_hint=None, domain_hint=None,
geolocation_hint=None, geolocation_hint=None,
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None, extension_attributes=None):
):
SamlBase.__init__(self, SamlBase.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.ip_hint = ip_hint or []
self.ip_hint=ip_hint or [] self.domain_hint = domain_hint or []
self.domain_hint=domain_hint or [] self.geolocation_hint = geolocation_hint or []
self.geolocation_hint=geolocation_hint or []
def disco_hints_type__from_string(xml_string): def disco_hints_type__from_string(xml_string):
return saml2.create_class_from_xml_string(DiscoHintsType_, xml_string) return saml2.create_class_from_xml_string(DiscoHintsType_, xml_string)
@@ -265,42 +278,48 @@ class UIInfoType_(SamlBase):
c_attributes = SamlBase.c_attributes.copy() c_attributes = SamlBase.c_attributes.copy()
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
c_children['{urn:oasis:names:tc:SAML:metadata:ui}DisplayName'] = ('display_name', [DisplayName]) c_children['{urn:oasis:names:tc:SAML:metadata:ui}DisplayName'] = (
c_cardinality['display_name'] = {"min":0} 'display_name', [DisplayName])
c_children['{urn:oasis:names:tc:SAML:metadata:ui}Description'] = ('description', [Description]) c_cardinality['display_name'] = {"min": 0}
c_cardinality['description'] = {"min":0} c_children['{urn:oasis:names:tc:SAML:metadata:ui}Description'] = (
c_children['{urn:oasis:names:tc:SAML:metadata:ui}Keywords'] = ('keywords', [Keywords]) 'description', [Description])
c_cardinality['keywords'] = {"min":0} c_cardinality['description'] = {"min": 0}
c_children['{urn:oasis:names:tc:SAML:metadata:ui}Keywords'] = (
'keywords', [Keywords])
c_cardinality['keywords'] = {"min": 0}
c_children['{urn:oasis:names:tc:SAML:metadata:ui}Logo'] = ('logo', [Logo]) c_children['{urn:oasis:names:tc:SAML:metadata:ui}Logo'] = ('logo', [Logo])
c_cardinality['logo'] = {"min":0} c_cardinality['logo'] = {"min": 0}
c_children['{urn:oasis:names:tc:SAML:metadata:ui}InformationURL'] = ('information_url', [InformationURL]) c_children['{urn:oasis:names:tc:SAML:metadata:ui}InformationURL'] = (
c_cardinality['information_url'] = {"min":0} 'information_url', [InformationURL])
c_children['{urn:oasis:names:tc:SAML:metadata:ui}PrivacyStatementURL'] = ('privacy_statement_url', [PrivacyStatementURL]) c_cardinality['information_url'] = {"min": 0}
c_cardinality['privacy_statement_url'] = {"min":0} c_children['{urn:oasis:names:tc:SAML:metadata:ui}PrivacyStatementURL'] = (
c_child_order.extend(['display_name', 'description', 'keywords', 'logo', 'information_url', 'privacy_statement_url']) 'privacy_statement_url', [PrivacyStatementURL])
c_cardinality['privacy_statement_url'] = {"min": 0}
c_child_order.extend(
['display_name', 'description', 'keywords', 'logo', 'information_url',
'privacy_statement_url'])
def __init__(self, def __init__(self,
display_name=None, display_name=None,
description=None, description=None,
keywords=None, keywords=None,
logo=None, logo=None,
information_url=None, information_url=None,
privacy_statement_url=None, privacy_statement_url=None,
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None, extension_attributes=None):
):
SamlBase.__init__(self, SamlBase.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.display_name = display_name or []
self.display_name=display_name or [] self.description = description or []
self.description=description or [] self.keywords = keywords or []
self.keywords=keywords or [] self.logo = logo or []
self.logo=logo or [] self.information_url = information_url or []
self.information_url=information_url or [] self.privacy_statement_url = privacy_statement_url or []
self.privacy_statement_url=privacy_statement_url or []
def ui_info_type__from_string(xml_string): def ui_info_type__from_string(xml_string):
return saml2.create_class_from_xml_string(UIInfoType_, xml_string) return saml2.create_class_from_xml_string(UIInfoType_, xml_string)
@@ -316,6 +335,7 @@ class DiscoHints(DiscoHintsType_):
c_child_order = DiscoHintsType_.c_child_order[:] c_child_order = DiscoHintsType_.c_child_order[:]
c_cardinality = DiscoHintsType_.c_cardinality.copy() c_cardinality = DiscoHintsType_.c_cardinality.copy()
def disco_hints_from_string(xml_string): def disco_hints_from_string(xml_string):
return saml2.create_class_from_xml_string(DiscoHints, xml_string) return saml2.create_class_from_xml_string(DiscoHints, xml_string)
@@ -330,6 +350,7 @@ class UIInfo(UIInfoType_):
c_child_order = UIInfoType_.c_child_order[:] c_child_order = UIInfoType_.c_child_order[:]
c_cardinality = UIInfoType_.c_cardinality.copy() c_cardinality = UIInfoType_.c_cardinality.copy()
def ui_info_from_string(xml_string): def ui_info_from_string(xml_string):
return saml2.create_class_from_xml_string(UIInfo, xml_string) return saml2.create_class_from_xml_string(UIInfo, xml_string)
@@ -375,4 +396,3 @@ ELEMENT_BY_TAG = {
def factory(tag, **kwargs): def factory(tag, **kwargs):
return ELEMENT_BY_TAG[tag](**kwargs) return ELEMENT_BY_TAG[tag](**kwargs)

View File

@@ -11,6 +11,7 @@ import xmldsig as ds
NAMESPACE = 'urn:mace:shibboleth:metadata:1.0' NAMESPACE = 'urn:mace:shibboleth:metadata:1.0'
class Scope(SamlBase): class Scope(SamlBase):
"""The urn:mace:shibboleth:metadata:1.0:Scope element """ """The urn:mace:shibboleth:metadata:1.0:Scope element """
@@ -24,17 +25,16 @@ class Scope(SamlBase):
c_attributes['regexp'] = ('regexp', 'boolean', False) c_attributes['regexp'] = ('regexp', 'boolean', False)
def __init__(self, def __init__(self,
regexp='false', regexp='false',
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None, extension_attributes=None):
):
SamlBase.__init__(self, SamlBase.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.regexp = regexp
self.regexp=regexp
def scope_from_string(xml_string): def scope_from_string(xml_string):
return saml2.create_class_from_xml_string(Scope, xml_string) return saml2.create_class_from_xml_string(Scope, xml_string)
@@ -49,25 +49,25 @@ class KeyAuthority(SamlBase):
c_attributes = SamlBase.c_attributes.copy() c_attributes = SamlBase.c_attributes.copy()
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
c_children['{http://www.w3.org/2000/09/xmldsig#}KeyInfo'] = ('key_info', [ds.KeyInfo]) c_children['{http://www.w3.org/2000/09/xmldsig#}KeyInfo'] = ('key_info',
c_cardinality['key_info'] = {"min":1} [ds.KeyInfo])
c_cardinality['key_info'] = {"min": 1}
c_attributes['VerifyDepth'] = ('verify_depth', 'unsignedByte', False) c_attributes['VerifyDepth'] = ('verify_depth', 'unsignedByte', False)
c_child_order.extend(['key_info']) c_child_order.extend(['key_info'])
def __init__(self, def __init__(self,
key_info=None, key_info=None,
verify_depth='1', verify_depth='1',
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None, extension_attributes=None):
):
SamlBase.__init__(self, SamlBase.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.key_info = key_info or []
self.key_info=key_info or [] self.verify_depth = verify_depth
self.verify_depth=verify_depth
def key_authority_from_string(xml_string): def key_authority_from_string(xml_string):
return saml2.create_class_from_xml_string(KeyAuthority, xml_string) return saml2.create_class_from_xml_string(KeyAuthority, xml_string)
@@ -86,4 +86,3 @@ ELEMENT_BY_TAG = {
def factory(tag, **kwargs): def factory(tag, **kwargs):
return ELEMENT_BY_TAG[tag](**kwargs) return ELEMENT_BY_TAG[tag](**kwargs)

View File

@@ -11,6 +11,7 @@ from saml2 import md
NAMESPACE = 'urn:oasis:names:tc:SAML:metadata:ui' NAMESPACE = 'urn:oasis:names:tc:SAML:metadata:ui'
class DisplayName(md.LocalizedNameType_): class DisplayName(md.LocalizedNameType_):
"""The urn:oasis:names:tc:SAML:metadata:ui:DisplayName element """ """The urn:oasis:names:tc:SAML:metadata:ui:DisplayName element """
@@ -21,6 +22,7 @@ class DisplayName(md.LocalizedNameType_):
c_child_order = md.LocalizedNameType_.c_child_order[:] c_child_order = md.LocalizedNameType_.c_child_order[:]
c_cardinality = md.LocalizedNameType_.c_cardinality.copy() c_cardinality = md.LocalizedNameType_.c_cardinality.copy()
def display_name_from_string(xml_string): def display_name_from_string(xml_string):
return saml2.create_class_from_xml_string(DisplayName, xml_string) return saml2.create_class_from_xml_string(DisplayName, xml_string)
@@ -35,6 +37,7 @@ class Description(md.LocalizedNameType_):
c_child_order = md.LocalizedNameType_.c_child_order[:] c_child_order = md.LocalizedNameType_.c_child_order[:]
c_cardinality = md.LocalizedNameType_.c_cardinality.copy() c_cardinality = md.LocalizedNameType_.c_cardinality.copy()
def description_from_string(xml_string): def description_from_string(xml_string):
return saml2.create_class_from_xml_string(Description, xml_string) return saml2.create_class_from_xml_string(Description, xml_string)
@@ -49,6 +52,7 @@ class InformationURL(md.LocalizedURIType_):
c_child_order = md.LocalizedURIType_.c_child_order[:] c_child_order = md.LocalizedURIType_.c_child_order[:]
c_cardinality = md.LocalizedURIType_.c_cardinality.copy() c_cardinality = md.LocalizedURIType_.c_cardinality.copy()
def information_url_from_string(xml_string): def information_url_from_string(xml_string):
return saml2.create_class_from_xml_string(InformationURL, xml_string) return saml2.create_class_from_xml_string(InformationURL, xml_string)
@@ -63,6 +67,7 @@ class PrivacyStatementURL(md.LocalizedURIType_):
c_child_order = md.LocalizedURIType_.c_child_order[:] c_child_order = md.LocalizedURIType_.c_child_order[:]
c_cardinality = md.LocalizedURIType_.c_cardinality.copy() c_cardinality = md.LocalizedURIType_.c_cardinality.copy()
def privacy_statement_url_from_string(xml_string): def privacy_statement_url_from_string(xml_string):
return saml2.create_class_from_xml_string(PrivacyStatementURL, xml_string) return saml2.create_class_from_xml_string(PrivacyStatementURL, xml_string)
@@ -79,24 +84,24 @@ class LogoType_(SamlBase):
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
c_attributes['height'] = ('height', 'positiveInteger', True) c_attributes['height'] = ('height', 'positiveInteger', True)
c_attributes['width'] = ('width', 'positiveInteger', True) c_attributes['width'] = ('width', 'positiveInteger', True)
c_attributes['{http://www.w3.org/XML/1998/namespace}lang'] = ('lang', 'anyURI', False) c_attributes['{http://www.w3.org/XML/1998/namespace}lang'] = (
'lang', 'anyURI', False)
def __init__(self, def __init__(self,
height=None, height=None,
width=None, width=None,
lang=None, lang=None,
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None, extension_attributes=None):
):
SamlBase.__init__(self, SamlBase.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.height = height
self.height=height self.width = width
self.width=width self.lang = lang
self.lang=lang
def logo_type__from_string(xml_string): def logo_type__from_string(xml_string):
return saml2.create_class_from_xml_string(LogoType_, xml_string) return saml2.create_class_from_xml_string(LogoType_, xml_string)
@@ -113,6 +118,7 @@ class IPHint(SamlBase):
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
def ip_hint_from_string(xml_string): def ip_hint_from_string(xml_string):
return saml2.create_class_from_xml_string(IPHint, xml_string) return saml2.create_class_from_xml_string(IPHint, xml_string)
@@ -128,6 +134,7 @@ class DomainHint(SamlBase):
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
def domain_hint_from_string(xml_string): def domain_hint_from_string(xml_string):
return saml2.create_class_from_xml_string(DomainHint, xml_string) return saml2.create_class_from_xml_string(DomainHint, xml_string)
@@ -143,6 +150,7 @@ class GeolocationHint(SamlBase):
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
def geolocation_hint_from_string(xml_string): def geolocation_hint_from_string(xml_string):
return saml2.create_class_from_xml_string(GeolocationHint, xml_string) return saml2.create_class_from_xml_string(GeolocationHint, xml_string)
@@ -157,6 +165,7 @@ class Logo(LogoType_):
c_child_order = LogoType_.c_child_order[:] c_child_order = LogoType_.c_child_order[:]
c_cardinality = LogoType_.c_cardinality.copy() c_cardinality = LogoType_.c_cardinality.copy()
def logo_from_string(xml_string): def logo_from_string(xml_string):
return saml2.create_class_from_xml_string(Logo, xml_string) return saml2.create_class_from_xml_string(Logo, xml_string)
@@ -170,30 +179,32 @@ class DiscoHintsType_(SamlBase):
c_attributes = SamlBase.c_attributes.copy() c_attributes = SamlBase.c_attributes.copy()
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
c_children['{urn:oasis:names:tc:SAML:metadata:ui}IPHint'] = ('ip_hint', [IPHint]) c_children['{urn:oasis:names:tc:SAML:metadata:ui}IPHint'] = (
c_cardinality['ip_hint'] = {"min":0} 'ip_hint', [IPHint])
c_children['{urn:oasis:names:tc:SAML:metadata:ui}DomainHint'] = ('domain_hint', [DomainHint]) c_cardinality['ip_hint'] = {"min": 0}
c_cardinality['domain_hint'] = {"min":0} c_children['{urn:oasis:names:tc:SAML:metadata:ui}DomainHint'] = (
c_children['{urn:oasis:names:tc:SAML:metadata:ui}GeolocationHint'] = ('geolocation_hint', [GeolocationHint]) 'domain_hint', [DomainHint])
c_cardinality['geolocation_hint'] = {"min":0} c_cardinality['domain_hint'] = {"min": 0}
c_children['{urn:oasis:names:tc:SAML:metadata:ui}GeolocationHint'] = (
'geolocation_hint', [GeolocationHint])
c_cardinality['geolocation_hint'] = {"min": 0}
c_child_order.extend(['ip_hint', 'domain_hint', 'geolocation_hint']) c_child_order.extend(['ip_hint', 'domain_hint', 'geolocation_hint'])
def __init__(self, def __init__(self,
ip_hint=None, ip_hint=None,
domain_hint=None, domain_hint=None,
geolocation_hint=None, geolocation_hint=None,
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None, extension_attributes=None):
):
SamlBase.__init__(self, SamlBase.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.ip_hint = ip_hint or []
self.ip_hint=ip_hint or [] self.domain_hint = domain_hint or []
self.domain_hint=domain_hint or [] self.geolocation_hint = geolocation_hint or []
self.geolocation_hint=geolocation_hint or []
def disco_hints_type__from_string(xml_string): def disco_hints_type__from_string(xml_string):
return saml2.create_class_from_xml_string(DiscoHintsType_, xml_string) return saml2.create_class_from_xml_string(DiscoHintsType_, xml_string)
@@ -208,38 +219,43 @@ class UIInfoType_(SamlBase):
c_attributes = SamlBase.c_attributes.copy() c_attributes = SamlBase.c_attributes.copy()
c_child_order = SamlBase.c_child_order[:] c_child_order = SamlBase.c_child_order[:]
c_cardinality = SamlBase.c_cardinality.copy() c_cardinality = SamlBase.c_cardinality.copy()
c_children['{urn:oasis:names:tc:SAML:metadata:ui}DisplayName'] = ('display_name', [DisplayName]) c_children['{urn:oasis:names:tc:SAML:metadata:ui}DisplayName'] = (
c_cardinality['display_name'] = {"min":0} 'display_name', [DisplayName])
c_children['{urn:oasis:names:tc:SAML:metadata:ui}Description'] = ('description', [Description]) c_cardinality['display_name'] = {"min": 0}
c_cardinality['description'] = {"min":0} c_children['{urn:oasis:names:tc:SAML:metadata:ui}Description'] = (
'description', [Description])
c_cardinality['description'] = {"min": 0}
c_children['{urn:oasis:names:tc:SAML:metadata:ui}Logo'] = ('logo', [Logo]) c_children['{urn:oasis:names:tc:SAML:metadata:ui}Logo'] = ('logo', [Logo])
c_cardinality['logo'] = {"min":0} c_cardinality['logo'] = {"min": 0}
c_children['{urn:oasis:names:tc:SAML:metadata:ui}InformationURL'] = ('information_url', [InformationURL]) c_children['{urn:oasis:names:tc:SAML:metadata:ui}InformationURL'] = (
c_cardinality['information_url'] = {"min":0} 'information_url', [InformationURL])
c_children['{urn:oasis:names:tc:SAML:metadata:ui}PrivacyStatementURL'] = ('privacy_statement_url', [PrivacyStatementURL]) c_cardinality['information_url'] = {"min": 0}
c_cardinality['privacy_statement_url'] = {"min":0} c_children['{urn:oasis:names:tc:SAML:metadata:ui}PrivacyStatementURL'] = (
c_child_order.extend(['display_name', 'description', 'logo', 'information_url', 'privacy_statement_url']) 'privacy_statement_url', [PrivacyStatementURL])
c_cardinality['privacy_statement_url'] = {"min": 0}
c_child_order.extend(
['display_name', 'description', 'logo', 'information_url',
'privacy_statement_url'])
def __init__(self, def __init__(self,
display_name=None, display_name=None,
description=None, description=None,
logo=None, logo=None,
information_url=None, information_url=None,
privacy_statement_url=None, privacy_statement_url=None,
text=None, text=None,
extension_elements=None, extension_elements=None,
extension_attributes=None, extension_attributes=None):
):
SamlBase.__init__(self, SamlBase.__init__(self,
text=text, text=text,
extension_elements=extension_elements, extension_elements=extension_elements,
extension_attributes=extension_attributes, extension_attributes=extension_attributes)
) self.display_name = display_name or []
self.display_name=display_name or [] self.description = description or []
self.description=description or [] self.logo = logo or []
self.logo=logo or [] self.information_url = information_url or []
self.information_url=information_url or [] self.privacy_statement_url = privacy_statement_url or []
self.privacy_statement_url=privacy_statement_url or []
def ui_info_type__from_string(xml_string): def ui_info_type__from_string(xml_string):
return saml2.create_class_from_xml_string(UIInfoType_, xml_string) return saml2.create_class_from_xml_string(UIInfoType_, xml_string)
@@ -255,6 +271,7 @@ class DiscoHints(DiscoHintsType_):
c_child_order = DiscoHintsType_.c_child_order[:] c_child_order = DiscoHintsType_.c_child_order[:]
c_cardinality = DiscoHintsType_.c_cardinality.copy() c_cardinality = DiscoHintsType_.c_cardinality.copy()
def disco_hints_from_string(xml_string): def disco_hints_from_string(xml_string):
return saml2.create_class_from_xml_string(DiscoHints, xml_string) return saml2.create_class_from_xml_string(DiscoHints, xml_string)
@@ -269,6 +286,7 @@ class UIInfo(UIInfoType_):
c_child_order = UIInfoType_.c_child_order[:] c_child_order = UIInfoType_.c_child_order[:]
c_cardinality = UIInfoType_.c_cardinality.copy() c_cardinality = UIInfoType_.c_cardinality.copy()
def ui_info_from_string(xml_string): def ui_info_from_string(xml_string):
return saml2.create_class_from_xml_string(UIInfo, xml_string) return saml2.create_class_from_xml_string(UIInfo, xml_string)

View File

@@ -56,6 +56,8 @@ REQ2SRV = {
ENTITYATTRIBUTES = "urn:oasis:names:tc:SAML:metadata:attribute&EntityAttributes" ENTITYATTRIBUTES = "urn:oasis:names:tc:SAML:metadata:attribute&EntityAttributes"
ENTITY_CATEGORY = "http://macedir.org/entity-category"
ENTITY_CATEGORY_SUPPORT = "http://macedir.org/entity-category-support"
# --------------------------------------------------- # ---------------------------------------------------
@@ -598,14 +600,14 @@ class MetadataStore(object):
if binding is None: if binding is None:
binding = BINDING_HTTP_REDIRECT binding = BINDING_HTTP_REDIRECT
return self.service(entity_id, "idpsso_descriptor", return self.service(entity_id, "idpsso_descriptor",
"single_sign_on_service", binding) "single_sign_on_service", binding)
def name_id_mapping_service(self, entity_id, binding=None, typ="idpsso"): def name_id_mapping_service(self, entity_id, binding=None, typ="idpsso"):
# IDP # IDP
if binding is None: if binding is None:
binding = BINDING_HTTP_REDIRECT binding = BINDING_HTTP_REDIRECT
return self.service(entity_id, "idpsso_descriptor", return self.service(entity_id, "idpsso_descriptor",
"name_id_mapping_service", binding) "name_id_mapping_service", binding)
def authn_query_service(self, entity_id, binding=None, def authn_query_service(self, entity_id, binding=None,
typ="authn_authority"): typ="authn_authority"):
@@ -613,7 +615,7 @@ class MetadataStore(object):
if binding is None: if binding is None:
binding = BINDING_SOAP binding = BINDING_SOAP
return self.service(entity_id, "authn_authority_descriptor", return self.service(entity_id, "authn_authority_descriptor",
"authn_query_service", binding) "authn_query_service", binding)
def attribute_service(self, entity_id, binding=None, def attribute_service(self, entity_id, binding=None,
typ="attribute_authority"): typ="attribute_authority"):
@@ -621,7 +623,7 @@ class MetadataStore(object):
if binding is None: if binding is None:
binding = BINDING_HTTP_REDIRECT binding = BINDING_HTTP_REDIRECT
return self.service(entity_id, "attribute_authority_descriptor", return self.service(entity_id, "attribute_authority_descriptor",
"attribute_service", binding) "attribute_service", binding)
def authz_service(self, entity_id, binding=None, typ="pdp"): def authz_service(self, entity_id, binding=None, typ="pdp"):
# PDP # PDP
@@ -773,13 +775,36 @@ class MetadataStore(object):
return [m["text"] for m in ad["affiliate_member"]] return [m["text"] for m in ad["affiliate_member"]]
def entity_categories(self, entity_id): def entity_categories(self, entity_id):
ext = self.__getitem__(entity_id)["extensions"] ent = self.__getitem__(entity_id)
res = [] res = []
for elem in ext["extension_elements"]: try:
if elem["__class__"] == ENTITYATTRIBUTES: ext = ent["extensions"]
for attr in elem["attribute"]: except KeyError:
if attr["name"] == "http://macedir.org/entity-category": pass
res.extend([v["text"] for v in attr["attribute_value"]]) else:
for elem in ext["extension_elements"]:
if elem["__class__"] == ENTITYATTRIBUTES:
for attr in elem["attribute"]:
if attr["name"] == ENTITY_CATEGORY:
res.extend([v["text"] for v in
attr["attribute_value"]])
return res
def supported_entity_categories(self, entity_id):
ent = self.__getitem__(entity_id)
res = []
try:
ext = ent["extensions"]
except KeyError:
pass
else:
for elem in ext["extension_elements"]:
if elem["__class__"] == ENTITYATTRIBUTES:
for attr in elem["attribute"]:
if attr["name"] == ENTITY_CATEGORY_SUPPORT:
res.extend([v["text"] for v in
attr["attribute_value"]])
return res return res

View File

@@ -23,6 +23,7 @@ import xmldsig as ds
from saml2.sigver import pre_signature_part from saml2.sigver import pre_signature_part
from saml2.s_utils import factory from saml2.s_utils import factory
from saml2.s_utils import rec_factory
from saml2.s_utils import sid from saml2.s_utils import sid
__author__ = 'rolandh' __author__ = 'rolandh'
@@ -51,6 +52,7 @@ ORG_ATTR_TRANSL = {
"organization_url": ("url", md.OrganizationURL) "organization_url": ("url", md.OrganizationURL)
} }
def metadata_tostring_fix(desc, nspair): def metadata_tostring_fix(desc, nspair):
MDNS = '"urn:oasis:names:tc:SAML:2.0:metadata"' MDNS = '"urn:oasis:names:tc:SAML:2.0:metadata"'
XMLNSXS = " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" XMLNSXS = " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
@@ -60,7 +62,7 @@ def metadata_tostring_fix(desc, nspair):
return xmlstring return xmlstring
def create_metadata_string(configfile, config, valid, cert, keyfile, id, name, def create_metadata_string(configfile, config, valid, cert, keyfile, mid, name,
sign): sign):
valid_for = 0 valid_for = 0
nspair = {"xs": "http://www.w3.org/2001/XMLSchema"} nspair = {"xs": "http://www.w3.org/2001/XMLSchema"}
@@ -85,8 +87,8 @@ def create_metadata_string(configfile, config, valid, cert, keyfile, id, name,
conf.xmlsec_binary = config.xmlsec_binary conf.xmlsec_binary = config.xmlsec_binary
secc = security_context(conf) secc = security_context(conf)
if id: if mid:
desc = entities_descriptor(eds, valid_for, name, id, desc = entities_descriptor(eds, valid_for, name, mid,
sign, secc) sign, secc)
valid_instance(desc) valid_instance(desc)
@@ -94,7 +96,7 @@ def create_metadata_string(configfile, config, valid, cert, keyfile, id, name,
else: else:
for eid in eds: for eid in eds:
if sign: if sign:
desc = sign_entity_descriptor(eid, id, secc) desc = sign_entity_descriptor(eid, mid, secc)
else: else:
desc = eid desc = eid
valid_instance(desc) valid_instance(desc)
@@ -111,8 +113,9 @@ def _localized_name(val, klass):
def do_organization_info(ava): def do_organization_info(ava):
""" decription of an organization in the configuration is """
a dictionary of keys and values, where the values might be tuples: Description of an organization in the configuration is
a dictionary of keys and values, where the values might be tuples::
"organization": { "organization": {
"name": ("AB Exempel", "se"), "name": ("AB Exempel", "se"),
@@ -372,6 +375,21 @@ DEFAULT_BINDING = {
} }
def do_extensions(mname, item):
try:
_mod = __import__("saml2.extension.%s" % mname, globals(), locals(),
mname)
except ImportError:
return None
else:
res = []
for _cname, ava in item.items():
cls = getattr(_mod, _cname)
res.append(rec_factory(cls, **ava))
return res
def _do_nameid_format(cls, conf, typ): def _do_nameid_format(cls, conf, typ):
namef = conf.getattr("name_id_format", typ) namef = conf.getattr("name_id_format", typ)
if namef: if namef:
@@ -421,19 +439,30 @@ def do_spsso_descriptor(conf, cert=None):
spsso = md.SPSSODescriptor() spsso = md.SPSSODescriptor()
spsso.protocol_support_enumeration = samlp.NAMESPACE spsso.protocol_support_enumeration = samlp.NAMESPACE
exts = conf.getattr("extensions", "sp")
if exts:
if spsso.extensions is None:
spsso.extensions = md.Extensions()
for key, val in exts.items():
_ext = do_extensions(key, val)
if _ext:
for _e in _ext:
spsso.extensions.add_extension_element(_e)
endps = conf.getattr("endpoints", "sp") endps = conf.getattr("endpoints", "sp")
if endps: if endps:
for (endpoint, instlist) in do_endpoints(endps, for (endpoint, instlist) in do_endpoints(endps,
ENDPOINTS["sp"]).items(): ENDPOINTS["sp"]).items():
setattr(spsso, endpoint, instlist) setattr(spsso, endpoint, instlist)
ext = do_endpoints(endps, ENDPOINT_EXT["sp"]) # ext = do_endpoints(endps, ENDPOINT_EXT["sp"])
if ext: # if ext:
if spsso.extensions is None: # if spsso.extensions is None:
spsso.extensions = md.Extensions() # spsso.extensions = md.Extensions()
for vals in ext.values(): # for vals in ext.values():
for val in vals: # for val in vals:
spsso.extensions.add_extension_element(val) # spsso.extensions.add_extension_element(val)
if cert: if cert:
encryption_type = conf.encryption_type encryption_type = conf.encryption_type
@@ -445,7 +474,7 @@ def do_spsso_descriptor(conf, cert=None):
if val is None: if val is None:
setattr(spsso, key, DEFAULT[key]) # default ?! setattr(spsso, key, DEFAULT[key]) # default ?!
else: else:
strval = "{0:>s}".format(val) strval = "{0:>s}".format(str(val))
setattr(spsso, key, strval.lower()) setattr(spsso, key, strval.lower())
except KeyError: except KeyError:
setattr(spsso, key, DEFAULTS[key]) setattr(spsso, key, DEFAULTS[key])

View File

@@ -413,7 +413,7 @@ def fticks_log(sp, logf, idp_entity_id, user_id, secret, assertion):
"PN": csum.hexdigest(), "PN": csum.hexdigest(),
"AM": ac.AuthnContextClassRef.text "AM": ac.AuthnContextClassRef.text
} }
logf.info(FTICKS_FORMAT % "#".join(["%s=%s" % (a,v) for a,v in info])) logf.info(FTICKS_FORMAT % "#".join(["%s=%s" % (a, v) for a, v in info]))
def dynamic_importer(name, class_name=None): def dynamic_importer(name, class_name=None):
@@ -428,14 +428,14 @@ def dynamic_importer(name, class_name=None):
try: try:
package = imp.load_module(name, fp, pathname, description) package = imp.load_module(name, fp, pathname, description)
except Exception, e: except Exception:
raise raise
if class_name: if class_name:
try: try:
_class = imp.load_module("%s.%s" % (name, class_name), fp, _class = imp.load_module("%s.%s" % (name, class_name), fp,
pathname, description) pathname, description)
except Exception, e: except Exception:
raise raise
return package, _class return package, _class
@@ -452,3 +452,34 @@ def exception_trace(exc):
_exc = "Exception: %s" % exc.message.encode("utf-8", "replace") _exc = "Exception: %s" % exc.message.encode("utf-8", "replace")
return {"message": _exc, "content": "".join(message)} return {"message": _exc, "content": "".join(message)}
def rec_factory(cls, **kwargs):
_inst = cls()
for key, val in kwargs.items():
if key in ["text", "lang"]:
setattr(_inst, key, val)
elif key in _inst.c_attributes:
try:
val = str(val)
except Exception:
continue
else:
setattr(_inst, key, val)
elif key in _inst.c_child_order:
for tag, _cls in _inst.c_children.values():
if tag == key:
if isinstance(_cls, list):
_cls = _cls[0]
claim = []
if isinstance(val, list):
for v in val:
claim.append(rec_factory(_cls, **v))
else:
claim.append(rec_factory(_cls, **val))
else:
claim = rec_factory(_cls, **val)
setattr(_inst, key, claim)
break
return _inst

View File

@@ -201,6 +201,18 @@ def valid_unsigned_short(val):
return True return True
def valid_positive_integer(val):
try:
integer = int(val)
except ValueError:
raise NotValid("positive integer")
if integer > 0:
return True
else:
raise NotValid("positive integer")
def valid_non_negative_integer(val): def valid_non_negative_integer(val):
try: try:
integer = int(val) integer = int(val)
@@ -269,6 +281,7 @@ VALIDATOR = {
"dateTime": valid_date_time, "dateTime": valid_date_time,
"anyURI": valid_any_uri, "anyURI": valid_any_uri,
"nonNegativeInteger": valid_non_negative_integer, "nonNegativeInteger": valid_non_negative_integer,
"PositiveInteger": valid_positive_integer,
"boolean": valid_boolean, "boolean": valid_boolean,
"unsignedShort": valid_unsigned_short, "unsignedShort": valid_unsigned_short,
"duration": valid_duration, "duration": valid_duration,

22
tests/enc_tmpl.xml Normal file
View File

@@ -0,0 +1,22 @@
<?xml version='1.0' encoding='UTF-8'?>
<ns0:EncryptedData xmlns:ns0="http://www.w3.org/2001/04/xmlenc#"
xmlns:ns1="http://www.w3.org/2000/09/xmldsig#" Id="ED"
Type="http://www.w3.org/2001/04/xmlenc#Element">
<ns0:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
<ns1:KeyInfo>
<ns0:EncryptedKey Id="EK">
<ns0:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
<ns1:KeyInfo>
<ns1:KeyName>my-rsa-key</ns1:KeyName>
</ns1:KeyInfo>
<ns0:CipherData>
<ns0:CipherValue/>
</ns0:CipherData>
</ns0:EncryptedKey>
</ns1:KeyInfo>
<ns0:CipherData>
<ns0:CipherValue/>
</ns0:CipherData>
</ns0:EncryptedData>

View File

@@ -7,6 +7,7 @@ from attribute_statement_data import *
from pathutils import full_path from pathutils import full_path
from saml2.attribute_converter import AttributeConverterNOOP from saml2.attribute_converter import AttributeConverterNOOP
from saml2.attribute_converter import to_local from saml2.attribute_converter import to_local
from saml2.saml import attribute_from_string
def _eq(l1,l2): def _eq(l1,l2):
@@ -205,8 +206,23 @@ def test_noop_attribute_conversion():
assert attr.attribute_value[0].text == "Roland" assert attr.attribute_value[0].text == "Roland"
ava = """<?xml version='1.0' encoding='UTF-8'?>
<ns0:Attribute xmlns:ns0="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" FriendlyName="schacHomeOrganization" Name="urn:oid:1.3.6.1.4.1.25178.1.2.9" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><ns0:AttributeValue xsi:nil="true" xsi:type="xs:string">uu.se</ns0:AttributeValue></ns0:Attribute>"""
def test_schac():
attr = attribute_from_string(ava)
acs = attribute_converter.ac_factory()
for ac in acs:
try:
res = ac.ava_from(attr)
assert res[0] == "schacHomeOrganization"
except KeyError:
pass
if __name__ == "__main__": if __name__ == "__main__":
t = TestAC() # t = TestAC()
t.setup_class() # t.setup_class()
t.test_mixed_attributes_1() # t.test_mixed_attributes_1()
#test_noop_attribute_conversion() test_schac()

99
tests/test_42_enc.py Normal file
View File

@@ -0,0 +1,99 @@
from saml2.authn_context import INTERNETPROTOCOLPASSWORD
from saml2.server import Server
from saml2.sigver import pre_encryption_part, ASSERT_XPATH, EncryptError
from saml2.sigver import CryptoBackendXmlSec1
from saml2.sigver import pre_encrypt_assertion
from pathutils import xmlsec_path
__author__ = 'roland'
TMPL = """<?xml version='1.0' encoding='UTF-8'?>
<ns0:EncryptedData xmlns:ns0="http://www.w3.org/2001/04/xmlenc#" xmlns:ns1="http://www.w3.org/2000/09/xmldsig#" Id="ED" Type="http://www.w3.org/2001/04/xmlenc#Element"><ns0:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /><ns1:KeyInfo><ns0:EncryptedKey Id="EK"><ns0:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /><ns1:KeyInfo><ns1:KeyName>my-rsa-key</ns1:KeyName></ns1:KeyInfo><ns0:CipherData><ns0:CipherValue /></ns0:CipherData></ns0:EncryptedKey></ns1:KeyInfo><ns0:CipherData><ns0:CipherValue /></ns0:CipherData></ns0:EncryptedData>"""
IDENTITY = {"eduPersonAffiliation": ["staff", "member"],
"surName": ["Jeter"], "givenName": ["Derek"],
"mail": ["foo@gmail.com"],
"title": ["shortstop"]}
AUTHN = {
"class_ref": INTERNETPROTOCOLPASSWORD,
"authn_auth": "http://www.example.com/login"
}
def test_pre_enc():
tmpl = pre_encryption_part()
print tmpl
assert "%s" % tmpl == TMPL
def test_reshuffle_response():
server = Server("idp_conf")
name_id = server.ident.transient_nameid(
"urn:mace:example.com:saml:roland:sp", "id12")
resp_ = server.create_authn_response(
IDENTITY, "id12", "http://lingon.catalogix.se:8087/",
"urn:mace:example.com:saml:roland:sp", name_id=name_id)
resp2 = pre_encrypt_assertion(resp_)
print resp2
assert resp2.encrypted_assertion.extension_elements
def test_enc1():
server = Server("idp_conf")
name_id = server.ident.transient_nameid(
"urn:mace:example.com:saml:roland:sp", "id12")
resp_ = server.create_authn_response(
IDENTITY, "id12", "http://lingon.catalogix.se:8087/",
"urn:mace:example.com:saml:roland:sp", name_id=name_id)
statement = pre_encrypt_assertion(resp_)
tmpl = "enc_tmpl.xml"
# tmpl_file = open(tmpl, "w")
# tmpl_file.write("%s" % pre_encryption_part())
# tmpl_file.close()
data = "pre_enc.xml"
# data_file = open(data, "w")
# data_file.write("%s" % statement)
# data_file.close()
key_type = "des-192"
com_list = [xmlsec_path, "encrypt", "--pubkey-cert-pem", "pubkey.pem",
"--session-key", key_type, "--xml-data", data,
"--node-xpath", ASSERT_XPATH]
crypto = CryptoBackendXmlSec1(xmlsec_path)
(_stdout, _stderr, output) = crypto._run_xmlsec(
com_list, [tmpl], exception=EncryptError, validate_output=False)
print output
assert _stderr == ""
assert _stdout == ""
def test_enc2():
crypto = CryptoBackendXmlSec1(xmlsec_path)
server = Server("idp_conf")
name_id = server.ident.transient_nameid(
"urn:mace:example.com:saml:roland:sp", "id12")
resp_ = server.create_authn_response(
IDENTITY, "id12", "http://lingon.catalogix.se:8087/",
"urn:mace:example.com:saml:roland:sp", name_id=name_id)
enc_resp = crypto.encrypt_assertion(resp_, "pubkey.pem",
pre_encryption_part())
print enc_resp
assert enc_resp
if __name__ == "__main__":
test_enc1()

View File

@@ -2,7 +2,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from saml2.authn_context import INTERNETPROTOCOLPASSWORD from saml2.authn_context import INTERNETPROTOCOLPASSWORD
from saml2 import saml
from saml2.server import Server from saml2.server import Server
from saml2.response import authn_response from saml2.response import authn_response
from saml2.config import config_factory from saml2.config import config_factory

View File

@@ -4,7 +4,8 @@ Testing CryptoBackendXMLSecurity with SoftHSM as backend
# Command to convert test.pem to PKCS#8 PEM format readable by softhsm : # Command to convert test.pem to PKCS#8 PEM format readable by softhsm :
# #
# openssl pkcs8 -topk8 -inform PEM -outform PEM -in test.key -out test.key.p8 -nocrypt # openssl pkcs8 -topk8 -inform PEM -outform PEM -in test.key -out test.key.p8
# -nocrypt
# #
__author__ = 'leifj' # based on p11_test from pyXMLSecurity __author__ = 'leifj' # based on p11_test from pyXMLSecurity

View File

@@ -0,0 +1,14 @@
from saml2.config import Config
from saml2.metadata import entity_descriptor
__author__ = 'roland'
fil = "sp_mdext_conf.py"
cnf = Config().load_file(fil, metadata_construction=True)
ed = entity_descriptor(cnf)
print ed
assert ed.spsso_descriptor.extensions
assert len(ed.spsso_descriptor.extensions.extension_elements) == 3