From d7f50d4b05472916cce2d52329da664c2751b7ce Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Thu, 13 Mar 2014 15:14:11 +0100 Subject: [PATCH] Refactored the support for metadata extensions in the config file. --- src/saml2/config.py | 12 ++- src/saml2/extension/mdrpi.py | 140 +++++++++++++------------ src/saml2/extension/mdui.py | 186 ++++++++++++++++++--------------- src/saml2/extension/shibmd.py | 53 +++++----- src/saml2/extension/ui.py | 150 ++++++++++++++------------ tests/enc_tmpl.xml | 22 ++++ tests/test_42_enc.py | 99 ++++++++++++++++++ tests/test_44_authnresp.py | 1 - tests/test_80_p11_backend.py | 3 +- tests/test_83_md_extensions.py | 14 +++ 10 files changed, 435 insertions(+), 245 deletions(-) create mode 100644 tests/enc_tmpl.xml create mode 100644 tests/test_42_enc.py create mode 100644 tests/test_83_md_extensions.py diff --git a/src/saml2/config.py b/src/saml2/config.py index f79d0a7..094a27f 100644 --- a/src/saml2/config.py +++ b/src/saml2/config.py @@ -68,7 +68,8 @@ COMMON_ARGS = [ "generate_cert_info", "tmp_cert_file", "tmp_key_file", - "validate_certificate" + "validate_certificate", + "extensions" ] SP_ARGS = [ @@ -213,6 +214,7 @@ class Config(object): self.tmp_cert_file = None self.tmp_key_file = None self.validate_certificate = None + self.extensions = {} def setattr(self, context, attr, val): if context == "": @@ -331,6 +333,9 @@ class Config(object): except KeyError: pass + if "extensions" in cnf: + self.do_extensions(cnf["extensions"]) + self.load_complex(cnf, metadata_construction=metadata_construction) self.context = self.def_context @@ -474,6 +479,11 @@ class Config(object): return None, None + def do_extensions(self, extensions): + for key, val in extensions.items(): + self.extensions[key] = val + + class SPConfig(Config): def_context = "sp" diff --git a/src/saml2/extension/mdrpi.py b/src/saml2/extension/mdrpi.py index 76e6e06..5951ed6 100644 --- a/src/saml2/extension/mdrpi.py +++ b/src/saml2/extension/mdrpi.py @@ -11,6 +11,7 @@ from saml2 import md NAMESPACE = 'urn:oasis:names:tc:SAML:metadata:rpi' + class RegistrationPolicy(md.LocalizedURIType_): """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_cardinality = md.LocalizedURIType_.c_cardinality.copy() + def registration_policy_from_string(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_cardinality = md.LocalizedURIType_.c_cardinality.copy() + def usage_policy_from_string(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) def __init__(self, - publisher=None, - creation_instant=None, - publication_id=None, - text=None, - extension_elements=None, - extension_attributes=None - ): - SamlBase.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.publisher=publisher - self.creation_instant=creation_instant - self.publication_id=publication_id + publisher=None, + creation_instant=None, + publication_id=None, + text=None, + extension_elements=None, + extension_attributes=None): + SamlBase.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.publisher = publisher + self.creation_instant = creation_instant + self.publication_id = publication_id + def publication_type__from_string(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_child_order = SamlBase.c_child_order[:] c_cardinality = SamlBase.c_cardinality.copy() - c_children['{urn:oasis:names:tc:SAML:metadata:rpi}RegistrationPolicy'] = ('registration_policy', [RegistrationPolicy]) - c_cardinality['registration_policy'] = {"min":0} - c_attributes['registrationAuthority'] = ('registration_authority', 'string', True) - c_attributes['registrationInstant'] = ('registration_instant', 'dateTime', False) + c_children['{urn:oasis:names:tc:SAML:metadata:rpi}RegistrationPolicy'] = ( + 'registration_policy', [RegistrationPolicy]) + c_cardinality['registration_policy'] = {"min": 0} + c_attributes['registrationAuthority'] = ( + 'registration_authority', 'string', True) + c_attributes['registrationInstant'] = ( + 'registration_instant', 'dateTime', False) c_child_order.extend(['registration_policy']) def __init__(self, - registration_policy=None, - registration_authority=None, - registration_instant=None, - text=None, - extension_elements=None, - extension_attributes=None - ): - SamlBase.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.registration_policy=registration_policy or [] - self.registration_authority=registration_authority - self.registration_instant=registration_instant + registration_policy=None, + registration_authority=None, + registration_instant=None, + text=None, + extension_elements=None, + extension_attributes=None): + SamlBase.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.registration_policy = registration_policy or [] + self.registration_authority = registration_authority + self.registration_instant = registration_instant + def registration_info_type__from_string(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_child_order = SamlBase.c_child_order[:] c_cardinality = SamlBase.c_cardinality.copy() - c_children['{urn:oasis:names:tc:SAML:metadata:rpi}UsagePolicy'] = ('usage_policy', [UsagePolicy]) - c_cardinality['usage_policy'] = {"min":0} + c_children['{urn:oasis:names:tc:SAML:metadata:rpi}UsagePolicy'] = ( + 'usage_policy', [UsagePolicy]) + c_cardinality['usage_policy'] = {"min": 0} c_attributes['publisher'] = ('publisher', 'string', True) c_attributes['creationInstant'] = ('creation_instant', 'dateTime', False) c_attributes['publicationId'] = ('publication_id', 'string', False) c_child_order.extend(['usage_policy']) def __init__(self, - usage_policy=None, - publisher=None, - creation_instant=None, - publication_id=None, - text=None, - extension_elements=None, - extension_attributes=None - ): - SamlBase.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.usage_policy=usage_policy or [] - self.publisher=publisher - self.creation_instant=creation_instant - self.publication_id=publication_id + usage_policy=None, + publisher=None, + creation_instant=None, + publication_id=None, + text=None, + extension_elements=None, + extension_attributes=None): + SamlBase.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.usage_policy = usage_policy or [] + self.publisher = publisher + self.creation_instant = creation_instant + self.publication_id = publication_id + def publication_info_type__from_string(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_cardinality = PublicationType_.c_cardinality.copy() + def publication_from_string(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_cardinality = RegistrationInfoType_.c_cardinality.copy() + def registration_info_from_string(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_cardinality = PublicationInfoType_.c_cardinality.copy() + def publication_info_from_string(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_child_order = SamlBase.c_child_order[:] c_cardinality = SamlBase.c_cardinality.copy() - c_children['{urn:oasis:names:tc:SAML:metadata:rpi}Publication'] = ('publication', [Publication]) - c_cardinality['publication'] = {"min":0} + c_children['{urn:oasis:names:tc:SAML:metadata:rpi}Publication'] = ( + 'publication', [Publication]) + c_cardinality['publication'] = {"min": 0} c_child_order.extend(['publication']) def __init__(self, - publication=None, - text=None, - extension_elements=None, - extension_attributes=None - ): - SamlBase.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.publication=publication or [] + publication=None, + text=None, + extension_elements=None, + extension_attributes=None): + SamlBase.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.publication = publication or [] + def publication_path_type__from_string(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_cardinality = PublicationPathType_.c_cardinality.copy() + def publication_path_from_string(xml_string): return saml2.create_class_from_xml_string(PublicationPath, xml_string) diff --git a/src/saml2/extension/mdui.py b/src/saml2/extension/mdui.py index 5dcd319..b27933c 100644 --- a/src/saml2/extension/mdui.py +++ b/src/saml2/extension/mdui.py @@ -11,6 +11,7 @@ from saml2 import md NAMESPACE = 'urn:oasis:names:tc:SAML:metadata:ui' + class DisplayName(md.LocalizedNameType_): """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_cardinality = md.LocalizedNameType_.c_cardinality.copy() + def display_name_from_string(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_cardinality = md.LocalizedNameType_.c_cardinality.copy() + def description_from_string(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_cardinality = md.LocalizedURIType_.c_cardinality.copy() + def information_url_from_string(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_cardinality = md.LocalizedURIType_.c_cardinality.copy() + def privacy_statement_url_from_string(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_cardinality = SamlBase.c_cardinality.copy() + def list_of_strings__from_string(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_child_order = ListOfStrings_.c_child_order[:] 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, - lang=None, - text=None, - extension_elements=None, - extension_attributes=None, - ): - ListOfStrings_.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.lang=lang + lang=None, + text=None, + extension_elements=None, + extension_attributes=None): + ListOfStrings_.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.lang = lang + def keywords_type__from_string(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_attributes['height'] = ('height', '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, - height=None, - width=None, - lang=None, - text=None, - extension_elements=None, - extension_attributes=None, - ): - SamlBase.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.height=height - self.width=width - self.lang=lang + height=None, + width=None, + lang=None, + text=None, + extension_elements=None, + extension_attributes=None): + SamlBase.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.height = height + self.width = width + self.lang = lang + def logo_type__from_string(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_cardinality = SamlBase.c_cardinality.copy() + def ip_hint_from_string(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_cardinality = SamlBase.c_cardinality.copy() + def domain_hint_from_string(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_cardinality = SamlBase.c_cardinality.copy() + def geolocation_hint_from_string(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_cardinality = KeywordsType_.c_cardinality.copy() + def keywords_from_string(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_cardinality = LogoType_.c_cardinality.copy() + def logo_from_string(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_child_order = SamlBase.c_child_order[:] c_cardinality = SamlBase.c_cardinality.copy() - c_children['{urn:oasis:names:tc:SAML:metadata:ui}IPHint'] = ('ip_hint', [IPHint]) - c_cardinality['ip_hint'] = {"min":0} - c_children['{urn:oasis:names:tc:SAML:metadata:ui}DomainHint'] = ('domain_hint', [DomainHint]) - 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_children['{urn:oasis:names:tc:SAML:metadata:ui}IPHint'] = ( + 'ip_hint', [IPHint]) + c_cardinality['ip_hint'] = {"min": 0} + c_children['{urn:oasis:names:tc:SAML:metadata:ui}DomainHint'] = ( + 'domain_hint', [DomainHint]) + 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']) def __init__(self, - ip_hint=None, - domain_hint=None, - geolocation_hint=None, - text=None, - extension_elements=None, - extension_attributes=None, - ): - SamlBase.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.ip_hint=ip_hint or [] - self.domain_hint=domain_hint or [] - self.geolocation_hint=geolocation_hint or [] + ip_hint=None, + domain_hint=None, + geolocation_hint=None, + text=None, + extension_elements=None, + extension_attributes=None): + SamlBase.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.ip_hint = ip_hint or [] + self.domain_hint = domain_hint or [] + self.geolocation_hint = geolocation_hint or [] + def disco_hints_type__from_string(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_child_order = SamlBase.c_child_order[:] c_cardinality = SamlBase.c_cardinality.copy() - c_children['{urn:oasis:names:tc:SAML:metadata:ui}DisplayName'] = ('display_name', [DisplayName]) - c_cardinality['display_name'] = {"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}Keywords'] = ('keywords', [Keywords]) - c_cardinality['keywords'] = {"min":0} + c_children['{urn:oasis:names:tc:SAML:metadata:ui}DisplayName'] = ( + 'display_name', [DisplayName]) + c_cardinality['display_name'] = {"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}Keywords'] = ( + 'keywords', [Keywords]) + c_cardinality['keywords'] = {"min": 0} c_children['{urn:oasis:names:tc:SAML:metadata:ui}Logo'] = ('logo', [Logo]) - c_cardinality['logo'] = {"min":0} - c_children['{urn:oasis:names:tc:SAML:metadata:ui}InformationURL'] = ('information_url', [InformationURL]) - c_cardinality['information_url'] = {"min":0} - c_children['{urn:oasis:names:tc:SAML:metadata:ui}PrivacyStatementURL'] = ('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']) + c_cardinality['logo'] = {"min": 0} + c_children['{urn:oasis:names:tc:SAML:metadata:ui}InformationURL'] = ( + 'information_url', [InformationURL]) + c_cardinality['information_url'] = {"min": 0} + c_children['{urn:oasis:names:tc:SAML:metadata:ui}PrivacyStatementURL'] = ( + '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, - display_name=None, - description=None, - keywords=None, - logo=None, - information_url=None, - privacy_statement_url=None, - text=None, - extension_elements=None, - extension_attributes=None, - ): - SamlBase.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.display_name=display_name or [] - self.description=description or [] - self.keywords=keywords or [] - self.logo=logo or [] - self.information_url=information_url or [] - self.privacy_statement_url=privacy_statement_url or [] + display_name=None, + description=None, + keywords=None, + logo=None, + information_url=None, + privacy_statement_url=None, + text=None, + extension_elements=None, + extension_attributes=None): + SamlBase.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.display_name = display_name or [] + self.description = description or [] + self.keywords = keywords or [] + self.logo = logo or [] + self.information_url = information_url or [] + self.privacy_statement_url = privacy_statement_url or [] + def ui_info_type__from_string(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_cardinality = DiscoHintsType_.c_cardinality.copy() + def disco_hints_from_string(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_cardinality = UIInfoType_.c_cardinality.copy() + def ui_info_from_string(xml_string): return saml2.create_class_from_xml_string(UIInfo, xml_string) @@ -375,4 +396,3 @@ ELEMENT_BY_TAG = { def factory(tag, **kwargs): return ELEMENT_BY_TAG[tag](**kwargs) - diff --git a/src/saml2/extension/shibmd.py b/src/saml2/extension/shibmd.py index 4da9976..0613f56 100644 --- a/src/saml2/extension/shibmd.py +++ b/src/saml2/extension/shibmd.py @@ -11,6 +11,7 @@ import xmldsig as ds NAMESPACE = 'urn:mace:shibboleth:metadata:1.0' + class Scope(SamlBase): """The urn:mace:shibboleth:metadata:1.0:Scope element """ @@ -24,17 +25,16 @@ class Scope(SamlBase): c_attributes['regexp'] = ('regexp', 'boolean', False) def __init__(self, - regexp='false', - text=None, - extension_elements=None, - extension_attributes=None, - ): - SamlBase.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.regexp=regexp + regexp='false', + text=None, + extension_elements=None, + extension_attributes=None): + SamlBase.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.regexp = regexp + def scope_from_string(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_child_order = SamlBase.c_child_order[:] c_cardinality = SamlBase.c_cardinality.copy() - c_children['{http://www.w3.org/2000/09/xmldsig#}KeyInfo'] = ('key_info', [ds.KeyInfo]) - c_cardinality['key_info'] = {"min":1} + c_children['{http://www.w3.org/2000/09/xmldsig#}KeyInfo'] = ('key_info', + [ds.KeyInfo]) + c_cardinality['key_info'] = {"min": 1} c_attributes['VerifyDepth'] = ('verify_depth', 'unsignedByte', False) c_child_order.extend(['key_info']) def __init__(self, - key_info=None, - verify_depth='1', - text=None, - extension_elements=None, - extension_attributes=None, - ): - SamlBase.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.key_info=key_info or [] - self.verify_depth=verify_depth + key_info=None, + verify_depth='1', + text=None, + extension_elements=None, + extension_attributes=None): + SamlBase.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.key_info = key_info or [] + self.verify_depth = verify_depth + def key_authority_from_string(xml_string): return saml2.create_class_from_xml_string(KeyAuthority, xml_string) @@ -86,4 +86,3 @@ ELEMENT_BY_TAG = { def factory(tag, **kwargs): return ELEMENT_BY_TAG[tag](**kwargs) - diff --git a/src/saml2/extension/ui.py b/src/saml2/extension/ui.py index 9fbaaee..aff4f75 100644 --- a/src/saml2/extension/ui.py +++ b/src/saml2/extension/ui.py @@ -11,6 +11,7 @@ from saml2 import md NAMESPACE = 'urn:oasis:names:tc:SAML:metadata:ui' + class DisplayName(md.LocalizedNameType_): """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_cardinality = md.LocalizedNameType_.c_cardinality.copy() + def display_name_from_string(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_cardinality = md.LocalizedNameType_.c_cardinality.copy() + def description_from_string(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_cardinality = md.LocalizedURIType_.c_cardinality.copy() + def information_url_from_string(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_cardinality = md.LocalizedURIType_.c_cardinality.copy() + def privacy_statement_url_from_string(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_attributes['height'] = ('height', '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, - height=None, - width=None, - lang=None, - text=None, - extension_elements=None, - extension_attributes=None, - ): - SamlBase.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.height=height - self.width=width - self.lang=lang + height=None, + width=None, + lang=None, + text=None, + extension_elements=None, + extension_attributes=None): + SamlBase.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.height = height + self.width = width + self.lang = lang + def logo_type__from_string(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_cardinality = SamlBase.c_cardinality.copy() + def ip_hint_from_string(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_cardinality = SamlBase.c_cardinality.copy() + def domain_hint_from_string(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_cardinality = SamlBase.c_cardinality.copy() + def geolocation_hint_from_string(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_cardinality = LogoType_.c_cardinality.copy() + def logo_from_string(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_child_order = SamlBase.c_child_order[:] c_cardinality = SamlBase.c_cardinality.copy() - c_children['{urn:oasis:names:tc:SAML:metadata:ui}IPHint'] = ('ip_hint', [IPHint]) - c_cardinality['ip_hint'] = {"min":0} - c_children['{urn:oasis:names:tc:SAML:metadata:ui}DomainHint'] = ('domain_hint', [DomainHint]) - 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_children['{urn:oasis:names:tc:SAML:metadata:ui}IPHint'] = ( + 'ip_hint', [IPHint]) + c_cardinality['ip_hint'] = {"min": 0} + c_children['{urn:oasis:names:tc:SAML:metadata:ui}DomainHint'] = ( + 'domain_hint', [DomainHint]) + 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']) def __init__(self, - ip_hint=None, - domain_hint=None, - geolocation_hint=None, - text=None, - extension_elements=None, - extension_attributes=None, - ): - SamlBase.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.ip_hint=ip_hint or [] - self.domain_hint=domain_hint or [] - self.geolocation_hint=geolocation_hint or [] + ip_hint=None, + domain_hint=None, + geolocation_hint=None, + text=None, + extension_elements=None, + extension_attributes=None): + SamlBase.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.ip_hint = ip_hint or [] + self.domain_hint = domain_hint or [] + self.geolocation_hint = geolocation_hint or [] + def disco_hints_type__from_string(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_child_order = SamlBase.c_child_order[:] c_cardinality = SamlBase.c_cardinality.copy() - c_children['{urn:oasis:names:tc:SAML:metadata:ui}DisplayName'] = ('display_name', [DisplayName]) - c_cardinality['display_name'] = {"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}DisplayName'] = ( + 'display_name', [DisplayName]) + c_cardinality['display_name'] = {"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_cardinality['logo'] = {"min":0} - c_children['{urn:oasis:names:tc:SAML:metadata:ui}InformationURL'] = ('information_url', [InformationURL]) - c_cardinality['information_url'] = {"min":0} - c_children['{urn:oasis:names:tc:SAML:metadata:ui}PrivacyStatementURL'] = ('privacy_statement_url', [PrivacyStatementURL]) - c_cardinality['privacy_statement_url'] = {"min":0} - c_child_order.extend(['display_name', 'description', 'logo', 'information_url', 'privacy_statement_url']) + c_cardinality['logo'] = {"min": 0} + c_children['{urn:oasis:names:tc:SAML:metadata:ui}InformationURL'] = ( + 'information_url', [InformationURL]) + c_cardinality['information_url'] = {"min": 0} + c_children['{urn:oasis:names:tc:SAML:metadata:ui}PrivacyStatementURL'] = ( + '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, - display_name=None, - description=None, - logo=None, - information_url=None, - privacy_statement_url=None, - text=None, - extension_elements=None, - extension_attributes=None, - ): - SamlBase.__init__(self, - text=text, - extension_elements=extension_elements, - extension_attributes=extension_attributes, - ) - self.display_name=display_name or [] - self.description=description or [] - self.logo=logo or [] - self.information_url=information_url or [] - self.privacy_statement_url=privacy_statement_url or [] + display_name=None, + description=None, + logo=None, + information_url=None, + privacy_statement_url=None, + text=None, + extension_elements=None, + extension_attributes=None): + SamlBase.__init__(self, + text=text, + extension_elements=extension_elements, + extension_attributes=extension_attributes) + self.display_name = display_name or [] + self.description = description or [] + self.logo = logo or [] + self.information_url = information_url or [] + self.privacy_statement_url = privacy_statement_url or [] + def ui_info_type__from_string(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_cardinality = DiscoHintsType_.c_cardinality.copy() + def disco_hints_from_string(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_cardinality = UIInfoType_.c_cardinality.copy() + def ui_info_from_string(xml_string): return saml2.create_class_from_xml_string(UIInfo, xml_string) diff --git a/tests/enc_tmpl.xml b/tests/enc_tmpl.xml new file mode 100644 index 0000000..599a943 --- /dev/null +++ b/tests/enc_tmpl.xml @@ -0,0 +1,22 @@ + + + + + + + + my-rsa-key + + + + + + + + + + \ No newline at end of file diff --git a/tests/test_42_enc.py b/tests/test_42_enc.py new file mode 100644 index 0000000..1a73b83 --- /dev/null +++ b/tests/test_42_enc.py @@ -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 = """ +my-rsa-key""" + +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() \ No newline at end of file diff --git a/tests/test_44_authnresp.py b/tests/test_44_authnresp.py index c6c405a..d4edb27 100644 --- a/tests/test_44_authnresp.py +++ b/tests/test_44_authnresp.py @@ -2,7 +2,6 @@ # -*- coding: utf-8 -*- from saml2.authn_context import INTERNETPROTOCOLPASSWORD -from saml2 import saml from saml2.server import Server from saml2.response import authn_response from saml2.config import config_factory diff --git a/tests/test_80_p11_backend.py b/tests/test_80_p11_backend.py index 779e198..4b36a9b 100644 --- a/tests/test_80_p11_backend.py +++ b/tests/test_80_p11_backend.py @@ -4,7 +4,8 @@ Testing CryptoBackendXMLSecurity with SoftHSM as backend # 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 diff --git a/tests/test_83_md_extensions.py b/tests/test_83_md_extensions.py new file mode 100644 index 0000000..1f37f4b --- /dev/null +++ b/tests/test_83_md_extensions.py @@ -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