From bc8715b0facd86f83296819b63c1800c5def1d09 Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Wed, 19 Aug 2009 09:00:10 +0200 Subject: [PATCH] Initial import --- TODO | 3 + setup.py | 36 + src/saml2/__init__.py | 437 +++++++++++ src/saml2/conftest.py | 20 + src/saml2/ds_test_data.py | 357 +++++++++ src/saml2/md.py | 1166 +++++++++++++++++++++++++++++ src/saml2/md_test_data.py | 1358 ++++++++++++++++++++++++++++++++++ src/saml2/saml.py | 951 ++++++++++++++++++++++++ src/saml2/samlp.py | 697 +++++++++++++++++ src/saml2/samlp_test_data.py | 454 ++++++++++++ src/saml2/test_base.py | 62 ++ src/saml2/test_data.py | 227 ++++++ src/saml2/test_utils.py | 30 + src/saml2/test_x_metadata.py | 86 +++ src/saml2/utils.py | 206 ++++++ src/xmldsig/__init__.py | 1058 ++++++++++++++++++++++++++ tests/ds_test.py | 655 ++++++++++++++++ tests/md_test.py | 1221 ++++++++++++++++++++++++++++++ tests/saml_test.py | 933 +++++++++++++++++++++++ tests/samlp_test.py | 535 ++++++++++++++ tests/test_b64.py | 62 ++ tests/test_from_string.py | 193 +++++ tests/test_md.py | 1152 ++++++++++++++++++++++++++++ tests/test_saml.py | 884 ++++++++++++++++++++++ 24 files changed, 12783 insertions(+) create mode 100644 TODO create mode 100755 setup.py create mode 100644 src/saml2/__init__.py create mode 100644 src/saml2/conftest.py create mode 100644 src/saml2/ds_test_data.py create mode 100644 src/saml2/md.py create mode 100644 src/saml2/md_test_data.py create mode 100644 src/saml2/saml.py create mode 100644 src/saml2/samlp.py create mode 100644 src/saml2/samlp_test_data.py create mode 100644 src/saml2/test_base.py create mode 100644 src/saml2/test_data.py create mode 100644 src/saml2/test_utils.py create mode 100644 src/saml2/test_x_metadata.py create mode 100644 src/saml2/utils.py create mode 100644 src/xmldsig/__init__.py create mode 100644 tests/ds_test.py create mode 100644 tests/md_test.py create mode 100644 tests/saml_test.py create mode 100644 tests/samlp_test.py create mode 100644 tests/test_b64.py create mode 100644 tests/test_from_string.py create mode 100644 tests/test_md.py create mode 100644 tests/test_saml.py diff --git a/TODO b/TODO new file mode 100644 index 0000000..3926ad2 --- /dev/null +++ b/TODO @@ -0,0 +1,3 @@ +1. Write documentations. +2. Write unittests for signature ralated utility methods. +3. Complete saml2 message class. diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..ce5c273 --- /dev/null +++ b/setup.py @@ -0,0 +1,36 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# Copyright (C) 2009 Umea Universitet, Sweden +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +from distutils.core import setup + + +setup( + name='python-saml2', + version='0.0.6', + description='Python client library for SAML Version 2', + long_description = """\ +python-saml2 is a library for SAML Version 2. +""", + author='Roland Hedberg', + author_email='roland.hedberg@adm.umu.se', + license='Apache 2.0', + url='http://code.google.com/p/python-saml2/', + packages=['saml2', 'xmldsig'], + package_dir = {'saml2':'src/saml2', 'xmldsig':'src/xmldsig'} +) diff --git a/src/saml2/__init__.py b/src/saml2/__init__.py new file mode 100644 index 0000000..bed8c6f --- /dev/null +++ b/src/saml2/__init__.py @@ -0,0 +1,437 @@ +#!/usr/bin/python +# +# Copyright (C) 2006 Google Inc. +# Copyright (C) 2009 Umea University +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Contains base classes representing Saml elements. + + These codes were originally written by Jeffrey Scudder for + representing Atom elements. Takashi Matsuo had added some codes, and + changed some. Roland Hedberg changed and added some more. + + Module objective: provide data classes for Saml constructs. These + classes hide the XML-ness of Saml and provide a set of native Python + classes to interact with. + + Conversions to and from XML should only be necessary when the Saml classes + "touch the wire" and are sent over HTTP. For this reason this module + provides methods and functions to convert Saml classes to and from strings. + + SamlBase: A foundation class on which Saml classes are built. It + handles the parsing of attributes and children which are common to all + Saml classes. By default, the SamlBase class translates all XML child + nodes into ExtensionElements. + + ExtensionElement: XML which is not part of the Saml specification, + these are called extension elements. If a classes parser + encounters an unexpected XML construct, it is translated into an + ExtensionElement instance. ExtensionElement is designed to fully + capture the information in the XML. Child nodes in an XML + extension are turned into ExtensionElements as well. + +""" + +try: + from xml.etree import cElementTree as ElementTree +except ImportError: + try: + import cElementTree as ElementTree + except ImportError: + from elementtree import ElementTree + +SAML_NAMESPACE = 'urn:oasis:names:tc:SAML:2.0:assertion' +SAML_TEMPLATE = '{urn:oasis:names:tc:SAML:2.0:assertion}%s' +XSI_NAMESPACE = 'http://www.w3.org/2001/XMLSchema-instance' + +NAMEID_FORMAT_EMAILADDRESS = ( + "urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress") +URN_PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password" +NAME_FORMAT_UNSPECIFIED = ( + "urn:oasis:names:tc:SAML:2.0:attrnam-format:unspecified") +NAME_FORMAT_URI = "urn:oasis:names:tc:SAML:2.0:attrnam-format:uri" +NAME_FORMAT_BASIC = "urn:oasis:names:tc:SAML:2.0:attrnam-format:basic" +SUBJECT_CONFIRMATION_METHOD_BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer" + +DECISION_TYPE_PERMIT = "Permit" +DECISION_TYPE_DENY = "Deny" +DECISION_TYPE_INDETERMINATE = "Indeterminate" + +V2 = "2.0" + +BINDING_SOAP = 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP' +BINDING_PAOS = 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' +BINDING_HTTP_REDIRECT = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect' +BINDING_HTTP_POST = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' +BINDING_HTTP_ARTIFACT = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' +BINDING_URI = 'urn:oasis:names:tc:SAML:2.0:bindings:URI' + +def create_class_from_xml_string(target_class, xml_string): + """Creates an instance of the target class from the string contents. + + :param target_class: The class which will be instantiated and populated + with the contents of the XML. This class must have a c_tag and a + c_namespace class variable. + :param xml_string: A string which contains valid XML. The root element + of the XML string should match the tag and namespace of the desired + class. + + :return: An instance of the target class with members assigned according to + the contents of the XML - or None if the root XML tag and namespace did + not match those of the target class. + """ + tree = ElementTree.fromstring(xml_string) + return _create_class_from_element_tree(target_class, tree) + + +def _create_class_from_element_tree(target_class, tree, namespace=None, + tag=None): + """Instantiates the class and populates members according to the tree. + + Note: Only use this function with classes that have c_namespace and c_tag + class members. + + :param target_class: The class which will be instantiated and populated + with the contents of the XML. + :param tree: An element tree whose contents will be converted into + members of the new target_class instance. + :param namespace: The namespace which the XML tree's root node must + match. If omitted, the namespace defaults to the c_namespace of the + target class. + :param tag: The tag which the XML tree's root node must match. If + omitted, the tag defaults to the c_tag class member of the target + class. + + :return: An instance of the target class - or None if the tag and namespace + of the XML tree's root node did not match the desired namespace and tag. + """ + if namespace is None: + namespace = target_class.c_namespace + if tag is None: + tag = target_class.c_tag + if tree.tag == '{%s}%s' % (namespace, tag): + target = target_class() + target.harvest_element_tree(tree) + return target + else: + return None + +class Error(Exception): + """Exception class thrown by this module.""" + pass + +class ExtensionElement(object): + """Represents extra XML elements contained in Saml classes.""" + + def __init__(self, tag, namespace=None, attributes=None, + children=None, text=None): + """Constructor for ExtensionElement + + :param namespace: The XML namespace for this element. + :param tag: The tag (without the namespace qualifier) for + this element. To reconstruct the full qualified name of the + element, combine this tag with the namespace. + :param attributes: The attribute value string pairs for the XML + attributes of this element. + :param children: list (optional) A list of ExtensionElements which + represent the XML child nodes of this element. + """ + + self.namespace = namespace + self.tag = tag + self.attributes = attributes or {} + self.children = children or [] + self.text = text + + def to_string(self): + """ Serialize the object into a XML string """ + element_tree = self._transfer_to_element_tree(ElementTree.Element('')) + return ElementTree.tostring(element_tree, encoding="UTF-8") + + def _transfer_to_element_tree(self, element_tree): + if self.tag is None: + return None + + if self.namespace is not None: + element_tree.tag = '{%s}%s' % (self.namespace, self.tag) + else: + element_tree.tag = self.tag + + for key, value in self.attributes.iteritems(): + element_tree.attrib[key] = value + + for child in self.children: + child.become_child_element(element_tree) + + element_tree.text = self.text + + return element_tree + + def become_child_element(self, element_tree): + """Converts this object into an etree element and adds it as a child + node. + + Adds self to the ElementTree. This method is required to avoid verbose + XML which constantly redefines the namespace. + + :param element_tree: ElementTree._Element The element to which this + object's XML will be added. + """ + new_element = ElementTree.Element('') + element_tree.append(new_element) + self._transfer_to_element_tree(new_element) + + def findc_children(self, tag=None, namespace=None): + """Searches child nodes for objects with the desired tag/namespace. + + Returns a list of extension elements within this object whose tag + and/or namespace match those passed in. To find all children in + a particular namespace, specify the namespace but not the tag name. + If you specify only the tag, the result list may contain extension + elements in multiple namespaces. + + Args: + tag: str (optional) The desired tag + namespace: str (optional) The desired namespace + + Returns: + A list of elements whose tag and/or namespace match the parameters + values + """ + + results = [] + + if tag and namespace: + for element in self.children: + if element.tag == tag and element.namespace == namespace: + results.append(element) + elif tag and not namespace: + for element in self.children: + if element.tag == tag: + results.append(element) + elif namespace and not tag: + for element in self.children: + if element.namespace == namespace: + results.append(element) + else: + for element in self.children: + results.append(element) + + return results + + +def extension_element_from_string(xml_string): + element_tree = ElementTree.fromstring(xml_string) + return _extension_element_from_element_tree(element_tree) + + +def _extension_element_from_element_tree(element_tree): + elementc_tag = element_tree.tag + if '}' in elementc_tag: + namespace = elementc_tag[1:elementc_tag.index('}')] + tag = elementc_tag[elementc_tag.index('}')+1:] + else: + namespace = None + tag = elementc_tag + extension = ExtensionElement(namespace=namespace, tag=tag) + for key, value in element_tree.attrib.iteritems(): + extension.attributes[key] = value + for child in element_tree: + extension.children.append(_extension_element_from_element_tree(child)) + extension.text = element_tree.text + return extension + + +class ExtensionContainer(object): + + c_tag = "" + c_namespace = "" + + def __init__(self, text=None, extension_elements=None, + extension_attributes=None): + + self.text = text + self.extension_elements = extension_elements or [] + self.extension_attributes = extension_attributes or {} + + # Three methods to create an object from an ElementTree + def harvest_element_tree(self, tree): + # Fill in the instance members from the contents of the XML tree. + for child in tree: + self._convert_element_tree_to_member(child) + for attribute, value in tree.attrib.iteritems(): + self._convert_element_attribute_to_member(attribute, value) + self.text = tree.text + + def _convert_element_tree_to_member(self, child_tree): + self.extension_elements.append(_extension_element_from_element_tree( + child_tree)) + + def _convert_element_attribute_to_member(self, attribute, value): + self.extension_attributes[attribute] = value + + # One method to create an ElementTree from an object + def _add_members_to_element_tree(self, tree): + for child in self.extension_elements: + child.become_child_element(tree) + for attribute, value in self.extension_attributes.iteritems(): + tree.attrib[attribute] = value + tree.text = self.text + + def find_extensions(self, tag=None, namespace=None): + """Searches extension elements for child nodes with the desired name. + + Returns a list of extension elements within this object whose tag + and/or namespace match those passed in. To find all extensions in + a particular namespace, specify the namespace but not the tag name. + If you specify only the tag, the result list may contain extension + elements in multiple namespaces. + + Args: + tag: str (optional) The desired tag + namespace: str (optional) The desired namespace + + Returns: + A list of elements whose tag and/or namespace match the parameters + values + """ + + results = [] + + if tag and namespace: + for element in self.extension_elements: + if element.tag == tag and element.namespace == namespace: + results.append(element) + elif tag and not namespace: + for element in self.extension_elements: + if element.tag == tag: + results.append(element) + elif namespace and not tag: + for element in self.extension_elements: + if element.namespace == namespace: + results.append(element) + else: + for element in self.extension_elements: + results.append(element) + + return results + + +class SamlBase(ExtensionContainer): + + c_children = {} + c_attributes = {} + c_child_order = [] + + def _get_allc_children_with_order(self): + if len(self.c_child_order) > 0: + for child in self.c_child_order: + yield child + else: + for _, values in self.__class__.c_children.iteritems(): + yield values[0] + + def _convert_element_tree_to_member(self, child_tree): + # Find the element's tag in this class's list of child members + if self.__class__.c_children.has_key(child_tree.tag): + member_name = self.__class__.c_children[child_tree.tag][0] + member_class = self.__class__.c_children[child_tree.tag][1] + # If the class member is supposed to contain a list, make sure the + # matching member is set to a list, then append the new member + # instance to the list. + if isinstance(member_class, list): + if getattr(self, member_name) is None: + setattr(self, member_name, []) + getattr(self, member_name).append( + _create_class_from_element_tree( + member_class[0], child_tree)) + else: + setattr(self, member_name, + _create_class_from_element_tree(member_class, + child_tree)) + else: + ExtensionContainer._convert_element_tree_to_member(self, + child_tree) + + def _convert_element_attribute_to_member(self, attribute, value): + # Find the attribute in this class's list of attributes. + if self.__class__.c_attributes.has_key(attribute): + # Find the member of this class which corresponds to the XML + # attribute(lookup in current_class.c_attributes) and set this + # member to the desired value (using self.__dict__). + setattr(self, self.__class__.c_attributes[attribute], value) + else: + ExtensionContainer._convert_element_attribute_to_member(self, + attribute, value) + + # Three methods to create an ElementTree from an object + def _add_members_to_element_tree(self, tree): + # Convert the members of this class which are XML child nodes. + # This uses the class's c_children dictionary to find the members which + # should become XML child nodes. + for member_name in self._get_allc_children_with_order(): + member = getattr(self, member_name) + if member is None: + pass + elif isinstance(member, list): + for instance in member: + instance.become_child_element(tree) + else: + member.become_child_element(tree) + # Convert the members of this class which are XML attributes. + for xml_attribute, member_name in \ + self.__class__.c_attributes.iteritems(): + member = getattr(self, member_name) + if member is not None: + tree.attrib[xml_attribute] = member + # Lastly, call the ExtensionContainers's _add_members_to_element_tree + # to convert any extension attributes. + ExtensionContainer._add_members_to_element_tree(self, tree) + + + def become_child_element(self, tree): + """ + + Note: Only for use with classes that have a c_tag and c_namespace class + member. It is in AtomBase so that it can be inherited but it should + not be called on instances of AtomBase. + + """ + new_child = ElementTree.Element('') + tree.append(new_child) + new_child.tag = '{%s}%s' % (self.__class__.c_namespace, + self.__class__.c_tag) + self._add_members_to_element_tree(new_child) + + def _to_element_tree(self): + """ + + Note, this method is designed to be used only with classes that have a + c_tag and c_namespace. It is placed in AtomBase for inheritance but should + not be called on this class. + + """ + new_tree = ElementTree.Element('{%s}%s' % (self.__class__.c_namespace, + self.__class__.c_tag)) + self._add_members_to_element_tree(new_tree) + return new_tree + + def to_string(self): + """Converts the Atom object to a string containing XML.""" + return ElementTree.tostring(self._to_element_tree(), encoding="UTF-8") + + def __str__(self): + return self.to_string() + + diff --git a/src/saml2/conftest.py b/src/saml2/conftest.py new file mode 100644 index 0000000..24b85e1 --- /dev/null +++ b/src/saml2/conftest.py @@ -0,0 +1,20 @@ +import py +import os +import time +from subprocess import Popen + +CONTACT = """ + + Roland + Hedberg + roland.hedberg@adm.umu.se +""" + +def pytest_funcarg__idp_metadata(request): + f = open('/Users/rolandh/code/om2/pysaml2/src/saml2/xeno_metadata.xml') + data = f.read() + f.close + return data + +def pytest_funcarg__contact(request): + return CONTACT diff --git a/src/saml2/ds_test_data.py b/src/saml2/ds_test_data.py new file mode 100644 index 0000000..ebd946d --- /dev/null +++ b/src/saml2/ds_test_data.py @@ -0,0 +1,357 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Test data for ds""" + +__author__ = 'tmatsuo@sios.com (Takashi MATSUO)' + +TEST_OBJECT = """ + + V2VkIEp1biAgNCAxMjoxMTowMyBFRFQgMjAwMwo + +""" + +TEST_MGMT_DATA = """ + + mgmt data + +""" + +TEST_SPKI_SEXP = """ + + spki sexp + +""" + +TEST_SPKI_DATA = """ + + spki sexp + spki sexp2 + +""" + +TEST_PGP_DATA = """ + + pgp key id + pgp key packet + +""" + +TEST_X509_ISSUER_SERIAL = """ + + issuer name + 1 + +""" + +TEST_X509_DATA = """ + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + +""" + +TEST_TRANSFORM = """ + + xpath + +""" + +TEST_TRANSFORMS = """ + + + xpath + + + xpath + + +""" + +TEST_RETRIEVAL_METHOD = """ + + + + xpath + + + xpath + + + +""" + +TEST_RSA_KEY_VALUE = """ + + modulus + exponent + +""" + +TEST_DSA_KEY_VALUE = """ + +

p

+ q + g + y + j + seed + pgen counter +
+""" + +TEST_KEY_VALUE1 = """ + + +

p

+ q + g + y + j + seed + pgen counter +
+
+""" + +TEST_KEY_VALUE2 = """ + + + modulus + exponent + + +""" + +TEST_KEY_NAME = """ + + key name + +""" + +TEST_KEY_INFO = """ + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+""" + +TEST_DIGEST_VALUE = """ + + digest value + +""" + +TEST_DIGEST_METHOD = """ + +""" + +TEST_REFERENCE = """ + + + + xpath + + + xpath + + + + digest value + +""" + +TEST_SIGNATURE_METHOD = """ + + 8 + +""" + +TEST_CANONICALIZATION_METHOD = """ + + +""" + +TEST_SIGNED_INFO = """ + + + + + 8 + + + + + xpath + + + xpath + + + + digest value + + +""" + +TEST_SIGNATURE_VALUE = """ + + signature value + +""" + +TEST_SIGNATURE = """ + + + + + + 8 + + + + + xpath + + + xpath + + + + digest value + + + + signature value + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + V2VkIEp1biAgNCAxMjoxMTowMyBFRFQgMjAwMwo + +
+""" diff --git a/src/saml2/md.py b/src/saml2/md.py new file mode 100644 index 0000000..28a0ece --- /dev/null +++ b/src/saml2/md.py @@ -0,0 +1,1166 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Contains classes representing Metadata elements. + + Module objective: provide data classes for Metadata + constructs. These classes hide the XML-ness of Saml and provide a + set of native Python classes to interact with. + +""" + +from saml2 import saml, SamlBase, create_class_from_xml_string +from saml2.saml import Attribute +import xmldsig as ds + +MD_NAMESPACE = 'urn:oasis:names:tc:SAML:2.0:metadata' +MD_TEMPLATE = '{urn:oasis:names:tc:SAML:2.0:metadata}%s' +XMLENC_NAMESPACE = 'http://www.w3.org/2001/04/xmlenc#' +XML_TEMPLATE = '{http://www.w3.org/XML/1998/namespace}%s' + +class Extensions(SamlBase): + """The md:Extensions element""" + + c_tag = 'Extensions' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def extensions_from_string(xml_string): + """ Create Extensions instance from an XML string """ + return create_class_from_xml_string(Extensions, xml_string) + +class LocalizedName(SamlBase): + """The md:LocalizedName abstract type""" + c_tag = 'LocalizedName' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes[XML_TEMPLATE % 'lang'] = 'lang' + + def __init__(self, lang=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for LocalizedName + + :param lang: xml:lang attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.lang = lang + +def localized_name_from_string(xml_string): + """ Create LocalizedName instance from an XML string """ + return create_class_from_xml_string(LocalizedName, xml_string) + +class LocalizedURI(SamlBase): + """The md:LocalizedURI abstract type""" + c_tag = 'LocalizedURI' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes[XML_TEMPLATE % 'lang'] = 'lang' + + def __init__(self, lang=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for LocalizedURI + + :param lang: xml:lang attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.lang = lang + +def localized_uri_from_string(xml_string): + """ Create LocalizedURI instance from an XML string """ + return create_class_from_xml_string(LocalizedURI, xml_string) + + +class OrganizationName(LocalizedName): + """The md:OrganizationName element""" + c_tag = 'OrganizationName' + c_namespace = MD_NAMESPACE + c_children = LocalizedName.c_children.copy() + c_attributes = LocalizedName.c_attributes.copy() + + def __init__(self, lang=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for OrganizationName + + :param lang: xml:lang attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + LocalizedName.__init__(self, lang, text, extension_elements, + extension_attributes) + + +def organization_name_from_string(xml_string): + """ Create OrganizationName instance from an XML string """ + return create_class_from_xml_string(OrganizationName, xml_string) + + +class OrganizationDisplayName(LocalizedName): + """The md:OrganizationDisplayName element""" + c_tag = 'OrganizationDisplayName' + c_namespace = MD_NAMESPACE + c_children = LocalizedName.c_children.copy() + c_attributes = LocalizedName.c_attributes.copy() + + def __init__(self, lang=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for OrganizationDisplayName + + :param lang: xml:lang attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + LocalizedName.__init__(self, lang, text, extension_elements, + extension_attributes) + + +def organization_display_name_from_string(xml_string): + """ Create OrganizationDisplayName instance from an XML string """ + return create_class_from_xml_string(OrganizationDisplayName, xml_string) + + +class OrganizationURL(LocalizedURI): + """The md:OrganizationURL element""" + c_tag = 'OrganizationURL' + c_namespace = MD_NAMESPACE + c_children = LocalizedURI.c_children.copy() + c_attributes = LocalizedURI.c_attributes.copy() + + def __init__(self, lang=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for OrganizationURL + + :param lang: xml:lang attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + LocalizedURI.__init__(self, lang, text, extension_elements, + extension_attributes) + + +def organization_url_from_string(xml_string): + """ Create OrganizationURL instance from an XML string """ + return create_class_from_xml_string(OrganizationURL, xml_string) + + +class Organization(SamlBase): + """The md:Organization base type""" + + c_tag = 'Organization' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_children['{%s}Extensions' % MD_NAMESPACE] = ('extensions', Extensions) + c_children['{%s}OrganizationName' % MD_NAMESPACE] = ( + 'organization_name', [OrganizationName]) + c_children['{%s}OrganizationDisplayName' % MD_NAMESPACE] = ( + 'organization_display_name', [OrganizationDisplayName]) + c_children['{%s}OrganizationURL' % MD_NAMESPACE] = ( + 'organization_url', [OrganizationURL]) + child_order = ['extensions', 'organization_name', + 'organization_display_name', 'organization_url'] + + def __init__(self, extensions=None, organization_name=None, + organization_display_name=None, organization_url=None, + text=None, extension_elements=None, extension_attributes=None): + """Constructor for Organization + + :param extensions: Extensions element + :param organization_name: OrganizationName elements + :param organization_display_name: OrganizationDisplayName elements + :param organization_url: OrganizationURL elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.extensions = extensions + self.organization_name = organization_name or [] + self.organization_display_name = organization_display_name or [] + self.organization_url = organization_url or [] + +def organization_from_string(xml_string): + """ Create Organization instance from an XML string """ + return create_class_from_xml_string(Organization, xml_string) + + +class Endpoint(SamlBase): + """The md:Endpoint base type""" + + c_tag = 'Endpoint' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['Binding'] = 'binding' + c_attributes['Location'] = 'location' + c_attributes['ResponseLocation'] = 'response_location' + + def __init__(self, binding=None, location=None, response_location=None, + text=None, extension_elements=None, extension_attributes=None): + """Constructor for Endpoint + + :param binding: Binding attribute + :param location: Location attribute + :param response_location: ResponseLocation attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.binding = binding + self.location = location + self.response_location = response_location + +def endpoint_from_string(xml_string): + """ Create Endpoint instance from an XML string """ + return create_class_from_xml_string(Endpoint, xml_string) + + +class IndexedEndpoint(Endpoint): + """The md:IndexedEndpoint base type""" + + c_tag = 'IndexedEndpoint' + c_namespace = MD_NAMESPACE + c_children = Endpoint.c_children.copy() + c_attributes = Endpoint.c_attributes.copy() + c_attributes['index'] = 'index' + c_attributes['isDefault'] = 'is_default' + + def __init__(self, index=None, is_default=None, binding=None, + location=None, response_location=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for IndexedEndpoint + + :param index: index attribute + :param is_default: isDefault attribute + :param binding: Binding attribute + :param location: Location attribute + :param response_location: ResponseLocation attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + Endpoint.__init__(self, binding, location, response_location, + text, extension_elements, extension_attributes) + self.index = index + self.is_default = is_default + +def indexed_endpoint_from_string(xml_string): + """ Create IndexedEndpoint instance from an XML string """ + return create_class_from_xml_string(IndexedEndpoint, xml_string) + + +class Company(SamlBase): + """The md:Company element""" + + c_tag = 'Company' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def company_from_string(xml_string): + """ Create Company instance from an XML string """ + return create_class_from_xml_string(Company, xml_string) + + +class GivenName(SamlBase): + """The md:GivenName element""" + + c_tag = 'GivenName' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def given_name_from_string(xml_string): + """ Create GivenName instance from an XML string """ + return create_class_from_xml_string(GivenName, xml_string) + + +class SurName(SamlBase): + """The md:SurName element""" + + c_tag = 'SurName' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def sur_name_from_string(xml_string): + """ Create SurName instance from an XML string """ + return create_class_from_xml_string(SurName, xml_string) + + +class EmailAddress(SamlBase): + """The md:EmailAddress element""" + + c_tag = 'EmailAddress' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def email_address_from_string(xml_string): + """ Create EmailAddress instance from an XML string """ + return create_class_from_xml_string(EmailAddress, xml_string) + + +class TelephoneNumber(SamlBase): + """The md:TelephoneNumber element""" + + c_tag = 'TelephoneNumber' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def telephone_number_from_string(xml_string): + """ Create TelephoneNumber instance from an XML string """ + return create_class_from_xml_string(TelephoneNumber, xml_string) + + +class ContactPerson(SamlBase): + """The md:ContactPerson element""" + + c_tag = 'ContactPerson' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['contactType'] = 'contact_type' + c_children['{%s}Extensions' % MD_NAMESPACE] = ('extensions', Extensions) + c_children['{%s}Company' % MD_NAMESPACE] = ('company', Company) + c_children['{%s}GivenName' % MD_NAMESPACE] = ('given_name', GivenName) + c_children['{%s}SurName' % MD_NAMESPACE] = ('sur_name', SurName) + c_children['{%s}EmailAddress' % MD_NAMESPACE] = ( + 'email_address', [EmailAddress]) + c_children['{%s}TelephoneNumber' % MD_NAMESPACE] = ( + 'telephone_number', [TelephoneNumber]) + c_child_order = ['extensions', 'company', 'given_name', 'sur_name', + 'email_address', 'telephone_number'] + + def __init__(self, extensions=None, contact_type=None, company=None, + given_name=None, sur_name=None, email_address=None, + telephone_number=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for ContactPerson + + :param extensions: Extensions element + :param contact_type: contactType attribute + :param company: Company element + :param given_name: GivenName element + :param sur_name: SurName element + :param email_address: EmailAddress elements + :param telephone_number: TelephoneNumber elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.contact_type = contact_type + self.extensions = extensions + self.company = company + self.given_name = given_name + self.sur_name = sur_name + self.email_address = email_address or [] + self.telephone_number = telephone_number or [] + +def contact_person_from_string(xml_string): + """ Create ContactPerson instance from an XML string """ + return create_class_from_xml_string(ContactPerson, xml_string) + + +class AdditionalMetadataLocation(SamlBase): + """The md:AdditionalMetadataLocation element""" + + c_tag = 'AdditionalMetadataLocation' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['namespace'] = 'namespace' + + def __init__(self, namespace=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for AdditionalMetadataLocation + + :param namespace: namespace attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.namespace = namespace + +def additional_metadata_location_from_string(xml_string): + """ Create AdditionalMetadataLocation instance from an XML string """ + return create_class_from_xml_string(AdditionalMetadataLocation, xml_string) + + +class KeySize(SamlBase): + """The xmlenc:KeySize element""" + + c_tag = 'KeySize' + c_namespace = XMLENC_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def key_size_from_string(xml_string): + """ Create KeySize instance from an XML string """ + return create_class_from_xml_string(KeySize, xml_string) + + +class OAEPparams(SamlBase): + """The xmlenc:OAEPparams element""" + + c_tag = 'OAEPparams' + c_namespace = XMLENC_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def oae_pparams_from_string(xml_string): + """ Create OAEPparams instance from an XML string """ + return create_class_from_xml_string(OAEPparams, xml_string) + + +class EncryptionMethod(SamlBase): + """The md:EncryptionMethod element""" + + c_tag = 'EncryptionMethod' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['Algorithm'] = 'algorithm' + c_children['{%s}KeySize' % XMLENC_NAMESPACE] = ('key_size', KeySize) + c_children['{%s}OAEPparams' % XMLENC_NAMESPACE] = ( + 'oaep_params', OAEPparams) + c_children['{%s}DigestMethod' % ds.DS_NAMESPACE] = ( + 'digest_method', ds.DigestMethod) + c_child_order = ['key_size', 'oaep_params', 'digest_method'] + + def __init__(self, algorithm=None, key_size=None, digest_method=None, + oaep_params=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for EncryptionMethod + + :param algorithm: Algorithm attribute + :param key_size: KeySize Element + :param digest_method: DigestMethod Element + :param oaep_params: OAEPparams Element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.algorithm = algorithm + self.key_size = key_size + self.digest_method = digest_method + self.oaep_params = oaep_params + +def encryption_method_from_string(xml_string): + """ Create EncryptionMethod instance from an XML string """ + return create_class_from_xml_string(EncryptionMethod, xml_string) + + +class KeyDescriptor(SamlBase): + """The md:KeyDescriptor element""" + + c_tag = 'KeyDescriptor' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['use'] = 'use' + c_children['{%s}KeyInfo' % ds.DS_NAMESPACE] = ('key_info', ds.KeyInfo) + c_children['{%s}EncryptionMethod' % MD_NAMESPACE] = ( + 'encryption_method', [EncryptionMethod]) + c_child_order = ['key_info', 'encryption_method'] + + def __init__(self, use=None, key_info=None, encryption_method=None, + text=None, extension_elements=None, + extension_attributes=None): + """Constructor for KeyDescriptor + + :param use: use attribute + :param key_info: KeyInfo element + :param encryption_method: EncryptionMethod elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.use = use + self.key_info = key_info + self.encryption_method = encryption_method or [] + +def key_descriptor_from_string(xml_string): + """ Create KeyDescriptor instance from an XML string """ + return create_class_from_xml_string(KeyDescriptor, xml_string) + + +class RoleDescriptor(SamlBase): + """The md:RoleDescriptor element""" + + c_tag = 'RoleDescriptor' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['ID'] = 'identifier' + c_attributes['validUntil'] = 'valid_until' + c_attributes['cacheDuration'] = 'cache_duration' + c_attributes['protocolSupportEnumeration'] = 'protocol_support_enumeration' + c_attributes['errorURL'] = 'error_url' + c_children['{%s}Signature' % ds.DS_NAMESPACE] = ('signature', ds.Signature) + c_children['{%s}Extensions' % MD_NAMESPACE] = ('extensions', Extensions) + c_children['{%s}KeyDescriptor' % MD_NAMESPACE] = ( + 'key_descriptor', [KeyDescriptor]) + c_children['{%s}Organization' % MD_NAMESPACE] = ( + 'organization', Organization) + c_children['{%s}ContactPerson' % MD_NAMESPACE] = ( + 'contact_person', [ContactPerson]) + c_child_order = ['signature', 'extensions', 'key_descriptor', + 'organization', 'contact_person'] + + def __init__(self, identifier=None, valid_until=None, cache_duration=None, + protocol_support_enumeration=None, error_url=None, + signature=None, extensions=None, key_descriptor=None, + organization=None, contact_person=None, + text=None, extension_elements=None, + extension_attributes=None): + """Constructor for RoleDescriptor + + :param identifier: ID attribute + :param valid_until: validUntil attribute + :param cache_duration: cacheDuration attribute + :param protocol_support_enumeration: protocolSupportEnumeration attribute + :param error_url: errorURL attribute + :param signature: ds:Signature element + :param extensions: Extensions element + :param key_descriptor: KeyDescriptor elements + :param organization: Organization element + :param contact_person: ContactPerson elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.identifier = identifier + self.valid_until = valid_until + self.cache_duration = cache_duration + self.protocol_support_enumeration = protocol_support_enumeration + self.error_url = error_url + self.signature = signature + self.extensions = extensions + self.key_descriptor = key_descriptor or [] + self.organization = organization + self.contact_person = contact_person or [] + +def role_descriptor_from_string(xml_string): + """ Create RoleDescriptor instance from an XML string """ + return create_class_from_xml_string(RoleDescriptor, xml_string) + + +class ArtifactResolutionService(IndexedEndpoint): + """The md:ArtifactResolutionService element""" + c_tag = 'ArtifactResolutionService' + +def artifact_resolution_service_from_string(xml_string): + """ Create ArtifactResolutionService instance from an XML string """ + return create_class_from_xml_string(ArtifactResolutionService, xml_string) + + +class AssertionConsumerService(IndexedEndpoint): + """The md:AssertionConsumerService element""" + c_tag = 'AssertionConsumerService' + +def assertion_consumer_service_from_string(xml_string): + """ Create AssertionConsumerService instance from an XML string """ + return create_class_from_xml_string(AssertionConsumerService, xml_string) + + +class SingleLogoutService(Endpoint): + """The md:SingleLogoutService element""" + c_tag = 'SingleLogoutService' + +def single_logout_service_from_string(xml_string): + """ Create SingleLogoutService instance from an XML string """ + return create_class_from_xml_string(SingleLogoutService, xml_string) + + +class ManageNameIDService(Endpoint): + """The md:ManageNameIDService element""" + c_tag = 'ManageNameIDService' + +def manage_name_id_service_from_string(xml_string): + """ Create ManageNameIDService instance from an XML string """ + return create_class_from_xml_string(ManageNameIDService, xml_string) + + +class NameIDFormat(SamlBase): + """The md:NameIDFormat element""" + + c_tag = 'NameIDFormat' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def name_id_format_from_string(xml_string): + """ Create NameIDFormat instance from an XML string """ + return create_class_from_xml_string(NameIDFormat, xml_string) + + +class SSODescriptor(RoleDescriptor): + """The md:SSODescriptor element""" + + c_tag = 'SSODescriptor' + c_namespace = MD_NAMESPACE + c_children = RoleDescriptor.c_children.copy() + c_attributes = RoleDescriptor.c_attributes.copy() + c_children['{%s}ArtifactResolutionService' % MD_NAMESPACE] = ( + 'artifact_resolution_service', [ArtifactResolutionService]) + c_children['{%s}SingleLogoutService' % MD_NAMESPACE] = ( + 'single_logout_service', [SingleLogoutService]) + c_children['{%s}ManageNameIDService' % MD_NAMESPACE] = ( + 'manage_name_id_service', [ManageNameIDService]) + c_children['{%s}NameIDFormat' % MD_NAMESPACE] = ( + 'name_id_format', [NameIDFormat]) + + c_child_order = ['signature', 'extensions', 'key_descriptor', + 'organization', 'contact_person', + 'artifact_resolution_service', 'single_logout_service', + 'manage_name_id_service', 'name_id_format'] + + def __init__(self, artifact_resolution_service=None, + single_logout_service=None, manage_name_id_service=None, + name_id_format=None, identifier=None, valid_until=None, + cache_duration=None, protocol_support_enumeration=None, + error_url=None, signature=None, extensions=None, + key_descriptor=None, organization=None, + contact_person=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for SSODescriptor + + :param artifact_resolution_service: ArtifactResolutionService elements + :param single_logout_service: SingleLogoutService elements + :param manage_name_id_service: ManageNameIDService elements + :param name_id_format: NameIDFormat elements + :param identifier: ID attribute + :param valid_until: validUntil attribute + :param cache_duration: cacheDuration attribute + :param protocol_support_enumeration: protocolSupportEnumeration attribute + :param error_url: errorURL attribute + :param signature: ds:Signature element + :param extensions: Extensions element + :param key_descriptor: KeyDescriptor elements + :param organization: Organization element + :param contact_person: ContactPerson elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + RoleDescriptor.__init__(self, identifier, valid_until, cache_duration, + protocol_support_enumeration, error_url, signature, + extensions, key_descriptor, organization, + contact_person, text, extension_elements, + extension_attributes) + + self.artifact_resolution_service = artifact_resolution_service or [] + self.single_logout_service = single_logout_service or [] + self.manage_name_id_service = manage_name_id_service or [] + self.name_id_format = name_id_format or [] + +def sso_descriptor_from_string(xml_string): + """ Create SSODescriptor instance from an XML string """ + return create_class_from_xml_string(SSODescriptor, xml_string) + + +class SingleSignOnService(Endpoint): + """The md:SingleSignOnService element""" + c_tag = 'SingleSignOnService' + +def single_sign_on_service_from_string(xml_string): + """ Create SingleSignOnService instance from an XML string """ + return create_class_from_xml_string(SingleSignOnService, xml_string) + + +class NameIDMappingService(Endpoint): + """The md:NameIDMappingService element""" + c_tag = 'NameIDMappingService' + +def name_id_mapping_service_from_string(xml_string): + """ Create NameIDMappingService instance from an XML string """ + return create_class_from_xml_string(NameIDMappingService, xml_string) + + +class AssertionIDRequestService(Endpoint): + """The md:AssertionIDRequestService element""" + c_tag = 'AssertionIDRequestService' + +def assertion_id_request_service_from_string(xml_string): + """ Create AssertionIDRequestService instance from an XML string """ + return create_class_from_xml_string(AssertionIDRequestService, xml_string) + + +class AttributeProfile(SamlBase): + """The md:AttributeProfile element""" + + c_tag = 'AttributeProfile' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def attribute_profile_from_string(xml_string): + """ Create AttributeProfile instance from an XML string """ + return create_class_from_xml_string(AttributeProfile, xml_string) + + +class IDPSSODescriptor(SSODescriptor): + """The md:IDPSSODescriptor element""" + + c_tag = 'IDPSSODescriptor' + c_namespace = MD_NAMESPACE + c_children = SSODescriptor.c_children.copy() + c_attributes = SSODescriptor.c_attributes.copy() + c_attributes['WantAuthnRequestsSigned'] = 'want_authn_requests_signed' + c_children['{%s}SingleSignOnService' % MD_NAMESPACE] = ( + 'single_sign_on_service', [SingleSignOnService]) + c_children['{%s}NameIDMappingService' % MD_NAMESPACE] = ( + 'name_id_mapping_service', [NameIDMappingService]) + c_children['{%s}AssertionIDRequestService' % MD_NAMESPACE] = ( + 'assertion_id_request_service', [AssertionIDRequestService]) + c_children['{%s}AttributeProfile' % MD_NAMESPACE] = ( + 'attribute_profile', [AttributeProfile]) + c_children['{%s}Attribute' % saml.SAML_NAMESPACE] = ( + 'attribute', [Attribute]) + + c_child_order = ['signature', 'extensions', 'key_descriptor', + 'organization', 'contact_person', + 'artifact_resolution_service', 'single_logout_service', + 'manage_name_id_service', 'name_id_format', + 'single_sign_on_service', 'name_id_mapping_service', + 'assertion_id_request_service', 'attribute_profile', + 'attribute'] + + def __init__(self, want_authn_requests_signed=None, + single_sign_on_service=None, name_id_mapping_service=None, + assertion_id_request_service=None, attribute_profile=None, + attribute=None, artifact_resolution_service=None, + single_logout_service=None, manage_name_id_service=None, + name_id_format=None, + identifier=None, valid_until=None, cache_duration=None, + protocol_support_enumeration=None, error_url=None, + signature=None, extensions=None, key_descriptor=None, + organization=None, contact_person=None, + text=None, + extension_elements=None, extension_attributes=None): + """Constructor for IDPSSODescriptor + + :param want_authn_requests_signed: WantAuthnRequestsSigned attribute + :param single_sign_on_service: SingleSignOnService elements + :param name_id_mapping_service: NameIDMappingService elements + :param assertion_id_request_service: AssertionIDRequestService elements + :param attribute_profile: AttributeProfile elements + :param attribute: Attribute elements + :param artifact_resolution_service: ArtifactResolutionService elements + :param single_logout_service: SingleLogoutService elements + :param manage_name_id_service: ManageNameIDService elements + :param name_id_format: NameIDFormat elements + :param identifier: ID attribute + :param valid_until: validUntil attribute + :param cache_duration: cacheDuration attribute + :param protocol_support_enumeration: protocolSupportEnumeration attribute + :param error_url: errorURL attribute + :param signature: ds:Signature element + :param extensions: Extensions element + :param key_descriptor: KeyDescriptor elements + :param organization: Organization element + :param contact_person: ContactPerson elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + SSODescriptor.__init__(self, artifact_resolution_service, + single_logout_service, manage_name_id_service, + name_id_format, identifier, valid_until, + cache_duration, protocol_support_enumeration, + error_url, signature, extensions, key_descriptor, + organization, contact_person, text, extension_elements, + extension_attributes) + + self.want_authn_requests_signed = want_authn_requests_signed + self.single_sign_on_service = single_sign_on_service or [] + self.name_id_mapping_service = name_id_mapping_service or [] + self.assertion_id_request_service = assertion_id_request_service or [] + self.attribute_profile = attribute_profile or [] + self.attribute = attribute or [] + +def idpsso_descriptor_from_string(xml_string): + """ Create IDPSSODescriptor instance from an XML string """ + return create_class_from_xml_string(IDPSSODescriptor, xml_string) + + +class RequestedAttribute(Attribute): + + c_tag = 'RequestedAttribute' + c_namespace = MD_NAMESPACE + c_children = Attribute.c_children.copy() + c_attributes = Attribute.c_attributes.copy() + c_attributes['isRequired'] = 'is_required' + + def __init__(self, is_required=None, name=None, name_format=None, + friendly_name=None, attribute_value=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for RequestedAttribute + + :param is_required: isRequired attribute + :param name: Name attribute + :param name_format: NameFormat attribute + :param friendly_name: FriendlyName attribute + :param attribute_value: AttributeValue elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + Attribute.__init__(self, name, name_format, friendly_name, + attribute_value, text, extension_elements, + extension_attributes) + self.is_required = is_required + +def requested_attribute_from_string(xml_string): + """ Create RequestedAttribute instance from an XML string """ + return create_class_from_xml_string(RequestedAttribute, xml_string) + + +class ServiceName(LocalizedName): + """The md:ServiceName element""" + c_tag = 'ServiceName' + c_namespace = MD_NAMESPACE + c_children = LocalizedName.c_children.copy() + c_attributes = LocalizedName.c_attributes.copy() + + def __init__(self, lang=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for ServiceName + + :param lang: xml:lang attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + LocalizedName.__init__(self, lang, text, extension_elements, + extension_attributes) + +def service_name_from_string(xml_string): + """ Create ServiceName instance from an XML string """ + return create_class_from_xml_string(ServiceName, xml_string) + + +class ServiceDescription(LocalizedName): + """The md:ServiceDescription element""" + c_tag = 'ServiceDescription' + c_namespace = MD_NAMESPACE + c_children = LocalizedName.c_children.copy() + c_attributes = LocalizedName.c_attributes.copy() + + def __init__(self, lang=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for ServiceDescription + + :param lang: xml:lang attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + LocalizedName.__init__(self, lang, text, extension_elements, + extension_attributes) + +def service_description_from_string(xml_string): + """ Create ServiceDescription instance from an XML string """ + return create_class_from_xml_string(ServiceDescription, xml_string) + + +class AttributeConsumingService(SamlBase): + """The md:AttributeConsumingService element""" + + c_tag = 'AttributeConsumingService' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['index'] = 'index' + c_attributes['isDefault'] = 'is_default' + c_children['{%s}ServiceName' % MD_NAMESPACE] = ( + 'service_name', [ServiceName]) + c_children['{%s}ServiceDescription' % MD_NAMESPACE] = ( + 'service_description', [ServiceDescription]) + c_children['{%s}RequestedAttribute' % MD_NAMESPACE] = ( + 'requested_attribute', [RequestedAttribute]) + c_child_order = ['service_name', 'service_description', + 'requested_attribute'] + + def __init__(self, index=None, is_default=None, service_name=None, + service_description=None, requested_attribute=None, + text=None, extension_elements=None, + extension_attributes=None): + """Constructor for AttributeConsumingService + + :param index: index attribute + :param is_default: isDefault attribute + :param service_name: ServiceName elements + :param service_descriptor: ServiceDescriptor elements + :param requested_attribute: RequestedAttribute elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.index = index + self.is_default = is_default + self.service_name = service_name or [] + self.service_description = service_description or [] + self.requested_attribute = requested_attribute or [] + +def attribute_consuming_service_from_string(xml_string): + """ Create AttributeConsumingService instance from an XML string """ + return create_class_from_xml_string(AttributeConsumingService, xml_string) + + +class SPSSODescriptor(SSODescriptor): + """The md:SPSSODescriptor element""" + + c_tag = 'SPSSODescriptor' + c_namespace = MD_NAMESPACE + c_children = SSODescriptor.c_children.copy() + c_attributes = SSODescriptor.c_attributes.copy() + c_attributes['AuthnRequestsSigned'] = 'authn_requests_signed' + c_attributes['WantAssertionsSigned'] = 'want_assertions_signed' + c_children['{%s}AssertionConsumerService' % MD_NAMESPACE] = ( + 'assertion_consumer_service', [AssertionConsumerService]) + c_children['{%s}AttributeConsumingService' % MD_NAMESPACE] = ( + 'attribute_consuming_service', [AttributeConsumingService]) + + c_child_order = ['signature', 'extensions', 'key_descriptor', + 'organization', 'contact_person', + 'artifact_resolution_service', 'single_logout_service', + 'manage_name_id_service', 'name_id_format', + 'assertion_consumer_service', + 'attribute_consuming_service'] + + def __init__(self, identifier=None, valid_until=None, cache_duration=None, + protocol_support_enumeration=None, error_url=None, + signature=None, extensions=None, key_descriptor=None, + organization=None, contact_person=None, + artifact_resolution_service=None, + single_logout_service=None, manage_name_id_service=None, + name_id_format=None, authn_requests_signed=None, + want_assertions_signed=None, + assertion_consumer_service=None, + attribute_consuming_service=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for IDPSSODescriptor + + :param identifier: ID attribute + :param valid_until: validUntil attribute + :param cache_duration: cacheDuration attribute + :param protocol_support_enumeration: protocolSupportEnumeration attribute + :param error_url: errorURL attribute + :param signature: ds:Signature element + :param extensions: Extensions element + :param key_descriptor: KeyDescriptor elements + :param organization: Organization element + :param contact_person: ContactPerson elements + :param artifact_resolution_service: ArtifactResolutionService elements + :param single_logout_service: SingleLogoutService elements + :param manage_name_id_service: ManageNameIDService elements + :param name_id_format: NameIDFormat elements + :param authn_requests_signed: AuthnRequestsSigned attribute + :param want_assertions_signed: WantAssertionsSigned attribute + :param assertion_consumer_service: AssertionConsumerService elements + :param attribute_consuming_service: AttributeConsumingService elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + SSODescriptor.__init__(self, artifact_resolution_service, + single_logout_service, manage_name_id_service, + name_id_format, identifier, valid_until, cache_duration, + protocol_support_enumeration, error_url, signature, + extensions, key_descriptor, organization, + contact_person, text, extension_elements, + extension_attributes) + + self.authn_requests_signed = authn_requests_signed + self.want_assertions_signed = want_assertions_signed + self.assertion_consumer_service = assertion_consumer_service or [] + self.attribute_consuming_service = attribute_consuming_service or [] + +def spsso_descriptor_from_string(xml_string): + """ Create SPSSODescriptor instance from an XML string """ + return create_class_from_xml_string(SPSSODescriptor, xml_string) + + +class EntityDescriptor(SamlBase): + """The md:EntityDescriptor element""" + #TODO: AuthnAuthorityDescriptor, AttributeAuthorityDescriptor, + # PDPDescriptor, + # AffiliationDescriptor is not implemented yet + + c_tag = 'EntityDescriptor' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['entityID'] = 'entity_id' + c_attributes['ID'] = 'identifier' + c_attributes['validUntil'] = 'valid_until' + c_attributes['cacheDuration'] = 'cache_duration' + c_children['{%s}Signature' % ds.DS_NAMESPACE] = ('signature', ds.Signature) + c_children['{%s}Extensions' % MD_NAMESPACE] = ('extensions', Extensions) + c_children['{%s}RoleDescriptor' % MD_NAMESPACE] = ( + 'role_descriptor', [RoleDescriptor]) + c_children['{%s}IDPSSODescriptor' % MD_NAMESPACE] = ( + 'idp_sso_descriptor', [IDPSSODescriptor]) + c_children['{%s}SPSSODescriptor' % MD_NAMESPACE] = ( + 'sp_sso_descriptor', [SPSSODescriptor]) + c_children['{%s}Organization' % MD_NAMESPACE] = ( + 'organization', Organization) + c_children['{%s}ContactPerson' % MD_NAMESPACE] = ( + 'contact_person', [ContactPerson]) + c_children['{%s}ContactPerson' % MD_NAMESPACE] = ( + 'contact_person', [ContactPerson]) + c_children['{%s}AdditionalMetadataLocation' % MD_NAMESPACE] = ( + 'additional_metadata_location', [AdditionalMetadataLocation]) + c_child_order = ['signature', 'extensions', 'role_descriptor', + 'idp_sso_descriptor', 'sp_sso_descriptor', 'organization', + 'contact_person', 'additional_metadata_location'] + + def __init__(self, entity_id=None, identifier=None, valid_until=None, + cache_duration=None, signature=None, extensions=None, + role_descriptor=None, idp_sso_descriptor=None, + sp_sso_descriptor=None, organization=None, + contact_person=None, additional_metadata_location=None, + text=None, extension_elements=None, + extension_attributes=None): + """Constructor for EntityDescriptor + + :param entity_id: entityID attribute + :param identifier: ID attribute + :param valid_until: validUntil attribute + :param cache_duration: cacheDuration attribute + :param signature: ds:Signature element + :param extensions: Extensions element + :param role_descriptor: RoleDescriptor elements + :param idp_sso_descriptor: IDPSSODescriptor elements + :param sp_sso_descriptor: SPSSODescriptor elements + :param organization: Organization element + :param contact_person: ContactPerson elements + :param additional_metadata_location: AdditionalMetadataLocation elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.entity_id = entity_id + self.identifier = identifier + self.valid_until = valid_until + self.cache_duration = cache_duration + self.signature = signature + self.extensions = extensions + self.role_descriptor = role_descriptor or [] + self.idp_sso_descriptor = idp_sso_descriptor or [] + self.sp_sso_descriptor = sp_sso_descriptor or [] + self.organization = organization + self.contact_person = contact_person or [] + self.additional_metadata_location = additional_metadata_location or [] + +def entity_descriptor_from_string(xml_string): + """ Create EntityDescriptor instance from an XML string """ + return create_class_from_xml_string(EntityDescriptor, xml_string) + + +class EntitiesDescriptor(SamlBase): + """The md:EntitiesDescriptor element""" + + c_tag = 'EntitiesDescriptor' + c_namespace = MD_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['name'] = 'name' + c_attributes['ID'] = 'identifier' + c_attributes['validUntil'] = 'valid_until' + c_attributes['cacheDuration'] = 'cache_duration' + c_children['{%s}Signature' % ds.DS_NAMESPACE] = ('signature', ds.Signature) + c_children['{%s}Extensions' % MD_NAMESPACE] = ('extensions', Extensions) + c_children['{%s}EntityDescriptor' % MD_NAMESPACE] = ( + 'entity_descriptor', [EntityDescriptor]) + c_child_order = ['signature', 'extensions', 'entity_descriptor', + 'entities_descriptor'] + + def __init__(self, name=None, identifier=None, valid_until=None, + cache_duration=None, signature=None, extensions=None, + entity_descriptor=None, entities_descriptor=None, + text=None, extension_elements=None, + extension_attributes=None): + """Constructor for EntitiesDescriptor + + :param name: name attribute + :param identifier: ID attribute + :param valid_until: validUntil attribute + :param cache_duration: cacheDuration attribute + :param signature: ds:Signature element + :param extensions: Extensions element + :param entity_descriptor: EntityDescriptor elements + :param entities_descriptor: EntitiesDescriptor elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.name = name + self.identifier = identifier + self.valid_until = valid_until + self.cache_duration = cache_duration + self.signature = signature + self.extensions = extensions + self.entity_descriptor = entity_descriptor or [] + self.entities_descriptor = entities_descriptor or [] + +EntitiesDescriptor.c_children['{%s}EntitiesDescriptor' % MD_NAMESPACE] = ( + 'entities_descriptor', [EntitiesDescriptor]) + +def entities_descriptor_from_string(xml_string): + """ Create EntitiesDescriptor instance from an XML string """ + return create_class_from_xml_string(EntitiesDescriptor, xml_string) + + diff --git a/src/saml2/md_test_data.py b/src/saml2/md_test_data.py new file mode 100644 index 0000000..cce1cde --- /dev/null +++ b/src/saml2/md_test_data.py @@ -0,0 +1,1358 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Test data for md""" + +__author__ = 'tmatsuo@sios.com (Takashi MATSUO)' + +TEST_ENDPOINT = """ + +""" + +TEST_SINGLE_LOGOUT_SERVICE = """ + +""" + + +TEST_MANAGE_NAMEID_SERVICE = """ + +""" + + +TEST_SINGLE_SIGN_ON_SERVICE = """ + +""" + + +TEST_NAME_ID_MAPPING_SERVICE = """ + +""" + + +TEST_ASSERTION_ID_REQUEST_SERVICE = """ + +""" + + +TEST_INDEXED_ENDPOINT = """ + +""" + +TEST_ARTIFACT_RESOLUTION_SERVICE = """ + +""" + +TEST_ASSERTION_CONSUMER_SERVICE = """ + +""" + +TEST_NAME_ID_FORMAT = """ + + urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress + +""" + +TEST_ATTRIBUTE_PROFILE = """ + + urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic + +""" + +TEST_ORGANIZATION_NAME = """ + + SIOS Technology, Inc. + +""" + +TEST_ORGANIZATION_DISPLAY_NAME = """ + + SIOS + +""" + +TEST_ORGANIZATION_URL = """ + + http://www.sios.com/ + +""" + +TEST_ORGANIZATION = """ + + + hogehoge + + + SIOS Technology, Inc. + + + SIOS + + + http://www.sios.com/ + + +""" + +TEST_CONTACT_PERSON = """ + + + hogehoge + + SIOS Technology, Inc. + Takashi + Matsuo + tmatsuo@sios.com + tmatsuo@shehas.net + 00-0000-0000 + +""" + +TEST_ADDITIONAL_METADATA_LOCATION = """ + + http://www.sios.com/AdditionalMetadataLocation + +""" + +TEST_KEY_SIZE = """ +128 +""" + +TEST_OAEP_PARAMS = """ + + 9lWu3Q== + +""" + +TEST_ENCRYPTION_METHOD = """ + + + 9lWu3Q== + + + +""" + +TEST_KEY_DESCRIPTOR = """ + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + + 9lWu3Q== + + + +
+""" + + +TEST_ROLE_DESCRIPTOR = """ + + + + + + + 8 + + + + + xpath + + + xpath + + + + digest value + + + + signature value + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + V2VkIEp1biAgNCAxMjoxMTowMyBFRFQgMjAwMwo + +
+ + bar + + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + + 9lWu3Q== + + + +
+ + + hogehoge + + + SIOS Technology, Inc. + + + SIOS + + + http://www.sios.com/ + + + + + hogehoge + + SIOS Technology, Inc. + Takashi + Matsuo + tmatsuo@sios.com + tmatsuo@shehas.net + 00-0000-0000 + +
+""" + + +TEST_SSO_DESCRIPTOR = """ + + + + + + + 8 + + + + + xpath + + + xpath + + + + digest value + + + + signature value + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + V2VkIEp1biAgNCAxMjoxMTowMyBFRFQgMjAwMwo + +
+ + bar + + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + + 9lWu3Q== + + + +
+ + + hogehoge + + + SIOS Technology, Inc. + + + SIOS + + + http://www.sios.com/ + + + + + hogehoge + + SIOS Technology, Inc. + Takashi + Matsuo + tmatsuo@sios.com + tmatsuo@shehas.net + 00-0000-0000 + + + + + + urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress + +
+""" + + +TEST_IDP_SSO_DESCRIPTOR = """ + + + + + + + 8 + + + + + xpath + + + xpath + + + + digest value + + + + signature value + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + V2VkIEp1biAgNCAxMjoxMTowMyBFRFQgMjAwMwo + +
+ + bar + + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + + 9lWu3Q== + + + +
+ + + hogehoge + + + SIOS Technology, Inc. + + + SIOS + + + http://www.sios.com/ + + + + + hogehoge + + SIOS Technology, Inc. + Takashi + Matsuo + tmatsuo@sios.com + tmatsuo@shehas.net + 00-0000-0000 + + + + + + urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress + + + + + + urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic + + + value1 of test attribute + value2 of test attribute + +
+""" + +TEST_REQUESTED_ATTRIBUTE = """ + + + value1 of test attribute + + + value2 of test attribute + + +""" + +TEST_SERVICE_NAME = """ + + SIOS mail + +""" + +TEST_SERVICE_DESCRIPTION = """ + + SIOS mail service + +""" + +TEST_ATTRIBUTE_CONSUMING_SERVICE = """ + +SIOS mail +SIOS mail service + + + value1 of test attribute + + + value2 of test attribute + + + +""" + + +TEST_SP_SSO_DESCRIPTOR = """ + + + + + + + 8 + + + + + xpath + + + xpath + + + + digest value + + + + signature value + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + V2VkIEp1biAgNCAxMjoxMTowMyBFRFQgMjAwMwo + +
+ + bar + + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + + 9lWu3Q== + + + +
+ + + hogehoge + + + SIOS Technology, Inc. + + + SIOS + + + http://www.sios.com/ + + + + + hogehoge + + SIOS Technology, Inc. + Takashi + Matsuo + tmatsuo@sios.com + tmatsuo@shehas.net + 00-0000-0000 + + + + + + urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress + + + +SIOS mail +SIOS mail service + + + value1 of test attribute + + + value2 of test attribute + + + +
+""" + +TEST_ENTITY_DESCRIPTOR = """ + + + + + + + 8 + + + + + xpath + + + xpath + + + + digest value + + + + signature value + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + V2VkIEp1biAgNCAxMjoxMTowMyBFRFQgMjAwMwo + +
+ + bar + + + + + + + hogehoge + + + SIOS Technology, Inc. + + + SIOS + + + http://www.sios.com/ + + + + + hogehoge + + SIOS Technology, Inc. + Takashi + Matsuo + tmatsuo@sios.com + tmatsuo@shehas.net + 00-0000-0000 + + + http://www.sios.com/AdditionalMetadataLocation + +
+""" + +TEST_ENTITIES_DESCRIPTOR = """ + + + + + + + 8 + + + + + xpath + + + xpath + + + + digest value + + + + signature value + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + V2VkIEp1biAgNCAxMjoxMTowMyBFRFQgMjAwMwo + +
+ + bar + + + + +""" diff --git a/src/saml2/saml.py b/src/saml2/saml.py new file mode 100644 index 0000000..5bac552 --- /dev/null +++ b/src/saml2/saml.py @@ -0,0 +1,951 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Contains classes representing Saml elements. + + Module objective: provide data classes for Saml constructs. These + classes hide the XML-ness of Saml and provide a set of native Python + classes to interact with. + + Conversions to and from XML should only be necessary when the Saml classes + "touch the wire" and are sent over HTTP. For this reason this module + provides methods and functions to convert Saml classes to and from strings. + + SamlBase: A foundation class on which Saml classes are built. It + handles the parsing of attributes and children which are common to all + Saml classes. By default, the SamlBase class translates all XML child + nodes into ExtensionElements. + + ExtensionElement: XML which is not part of the Saml specification, + these are called extension elements. If a classes parser + encounters an unexpected XML construct, it is translated into an + ExtensionElement instance. ExtensionElement is designed to fully + capture the information in the XML. Child nodes in an XML + extension are turned into ExtensionElements as well. +""" + +import xmldsig as ds +import saml2 +from saml2 import SamlBase + +SAML_NAMESPACE = 'urn:oasis:names:tc:SAML:2.0:assertion' +SAML_TEMPLATE = '{urn:oasis:names:tc:SAML:2.0:assertion}%s' +XSI_NAMESPACE = 'http://www.w3.org/2001/XMLSchema-instance' + +NAMEID_FORMAT_EMAILADDRESS = ( + "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress") +NAMEID_FORMAT_UNSPECIFIED = ( + "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified") +NAMEID_FORMAT_ENCRYPTED = ( + "urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted") +NAMEID_FORMAT_PERSISTENT = ( + "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent") + +PROFILE_ATTRIBUTE_BASIC = ( + "urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic") + +URN_PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password" +NAME_FORMAT_UNSPECIFIED = ( + "urn:oasis:names:tc:SAML:2.0:attrnam-format:unspecified") +NAME_FORMAT_URI = "urn:oasis:names:tc:SAML:2.0:attrnam-format:uri" +NAME_FORMAT_BASIC = "urn:oasis:names:tc:SAML:2.0:attrnam-format:basic" +SUBJECT_CONFIRMATION_METHOD_BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer" + +DECISION_TYPE_PERMIT = "Permit" +DECISION_TYPE_DENY = "Deny" +DECISION_TYPE_INDETERMINATE = "Indeterminate" + +CONSENT_UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:consent:unspecified" +V2 = "2.0" + +class BaseID(SamlBase): + """The saml:BaseID element""" + + c_tag = 'BaseID' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['NameQualifier'] = 'name_qualifier' + c_attributes['SPNameQualifier'] = 'sp_name_qualifier' + + def __init__(self, name_qualifier=None, sp_name_qualifier=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for BaseID + + :param name_qualifier: NameQualifier attribute + :param sp_name_qualifier: SPNameQualifier attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.name_qualifier = name_qualifier + self.sp_name_qualifier = sp_name_qualifier + +def base_id_from_string(xml_string): + """ Create BaseID instance from an XML string """ + return saml2.create_class_from_xml_string(BaseID, xml_string) + + +class NameID(BaseID): + """The saml:NameID element""" + + c_tag = 'NameID' + c_namespace = SAML_NAMESPACE + c_children = BaseID.c_children.copy() + c_attributes = BaseID.c_attributes.copy() + c_attributes['Format'] = 'name_format' + c_attributes['SPProvidedID'] = 'sp_provided_id' + + def __init__(self, name_qualifier=None, sp_name_qualifier=None, + name_format=None, sp_provided_id=None, + text=None, extension_elements=None, + extension_attributes=None): + """Constructor for NameID + + :param format: Format attribute + :param sp_provided_id: SPProvidedID attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + BaseID.__init__(self, name_qualifier, sp_name_qualifier, text, + extension_elements, extension_attributes) + + self.name_format = name_format + self.sp_provided_id = sp_provided_id + +def name_id_from_string(xml_string): + """ Create NameID instance from an XML string """ + return saml2.create_class_from_xml_string(NameID, xml_string) + + +class Issuer(NameID): + """The saml:Issuer element""" + + c_tag = 'Issuer' + c_children = NameID.c_children.copy() + c_attributes = NameID.c_attributes.copy() + +def issuer_from_string(xml_string): + """ Create Issuer instance from an XML string """ + return saml2.create_class_from_xml_string(Issuer, xml_string) + + +class SubjectLocality(SamlBase): + """The saml:SubjectLocality element""" + + c_tag = 'SubjectLocality' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['Address'] = 'address' + c_attributes['DNSName'] = 'dns_name' + + def __init__(self, address=None, dns_name=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for SubjectLocality + + :param address: Address attribute + :param dns_name: DNSName attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.address = address + self.dns_name = dns_name + +def subject_locality_from_string(xml_string): + """ Create SubjectLocality instance from an XML string """ + return saml2.create_class_from_xml_string(SubjectLocality, xml_string) + + +class AuthnContextClassRef(SamlBase): + """The saml:AuthnContextClassRef element""" + + c_tag = 'AuthnContextClassRef' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def authn_context_class_ref_from_string(xml_string): + """ Create AuthnContextClassRef instance from an XML string """ + return saml2.create_class_from_xml_string(AuthnContextClassRef, xml_string) + + +class AuthnContextDeclRef(SamlBase): + """The saml:AuthnContextDeclRef element""" + + c_tag = 'AuthnContextDeclRef' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def authn_context_decl_ref_from_string(xml_string): + """ Create AuthnContextDeclRef instance from an XML string """ + return saml2.create_class_from_xml_string(AuthnContextDeclRef, xml_string) + + +class AuthnContextDecl(SamlBase): + """The saml:AuthnContextDecl element""" + + c_tag = 'AuthnContextDecl' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def authn_context_decl_from_string(xml_string): + """ Create AuthnContextDecl instance from an XML string """ + return saml2.create_class_from_xml_string(AuthnContextDecl, xml_string) + + +class AuthenticatingAuthority(SamlBase): + """The saml:AuthenticatingAuthority element""" + + c_tag = 'AuthenticatingAuthority' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def authenticating_authority_from_string(xml_string): + """ Create AuthenticatingAuthority instance from an XML string """ + return saml2.create_class_from_xml_string(AuthenticatingAuthority, + xml_string) + + +class AuthnContext(SamlBase): + """The saml:AuthnContext element""" + + c_tag = 'AuthnContext' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_children['{%s}AuthnContextClassRef' % SAML_NAMESPACE] = ( + 'authn_context_class_ref', AuthnContextClassRef) + c_children['{%s}AuthnContextDeclRef' % SAML_NAMESPACE] = ( + 'authn_context_decl_ref', AuthnContextDeclRef) + c_children['{%s}AuthnContextDecl' % SAML_NAMESPACE] = ( + 'authn_context_decl', AuthnContextDecl) + c_children['{%s}AuthenticatingAuthority' % SAML_NAMESPACE] = ( + 'authenticating_authority', [AuthenticatingAuthority]) + c_child_order = ['authn_context_class_ref', 'authn_context_decl_ref', + 'authn_context_decl', 'authenticating_authority'] + + def __init__(self, authn_context_class_ref=None, + authn_context_decl_ref=None, + authn_context_decl=None, authenticating_authority=None, + text=None, extension_elements=None, + extension_attributes=None): + """Constructor for AuthnContext + + Args: + :param authn_context_class_ref: AuthnContextClassRef element + :param authn_context_decl_ref: AuthnContextDeclRef element + :param authn_context_decl: AuthnContextDecl element + :param authenticating_authority: AuthenticatingAuthority element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + SamlBase.__init__(self, text, extension_elements, extension_attributes) + + self.authn_context_class_ref = authn_context_class_ref + self.authn_context_decl_ref = authn_context_decl_ref + self.authn_context_decl = authn_context_decl + self.authenticating_authority = authenticating_authority or [] + +def authn_context_from_string(xml_string): + """ Create AuthnContext instance from an XML string """ + return saml2.create_class_from_xml_string(AuthnContext, xml_string) + +class Statement(SamlBase): + """The saml:Statement element""" + + c_tag = 'Statement' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def statement_from_string(xml_string): + """ Create Statement instance from an XML string """ + return saml2.create_class_from_xml_string(Statement, xml_string) + + +class AuthnStatement(Statement): + """The saml:AuthnStatement element""" + + c_tag = 'AuthnStatement' + c_namespace = SAML_NAMESPACE + c_children = Statement.c_children.copy() + c_attributes = Statement.c_attributes.copy() + c_attributes['AuthnInstant'] = 'authn_instant' + c_attributes['SessionIndex'] = 'session_index' + c_attributes['SessionNotOnOrAfter'] = 'session_not_on_or_after' + c_children['{%s}SubjectLocality' % SAML_NAMESPACE] = ( + 'subject_locality', SubjectLocality) + c_children['{%s}AuthnContext' % SAML_NAMESPACE] = ( + 'authn_context', AuthnContext) + c_child_order = ['subject_locality', 'authn_context'] + + def __init__(self, authn_instant=None, session_index=None, + session_not_on_or_after=None, subject_locality=None, + authn_context=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for AuthnStatement + + :param authn_instant: AuthnInstant attribute + :param session_index: SessionIndex attribute + :param session_not_on_or_after: SessionNotOnOrAfter attribute + :param subject_locality: SubjectLocality element + :param authn_context: AuthnContext element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + Statement.__init__(self, extension_elements, extension_attributes, + text) + + self.authn_instant = authn_instant + self.session_index = session_index + self.session_not_on_or_after = session_not_on_or_after + self.subject_locality = subject_locality + self.authn_context = authn_context + +def authn_statement_from_string(xml_string): + """ Create AuthnStatement instance from an XML string """ + return saml2.create_class_from_xml_string(AuthnStatement, xml_string) + +# TODO: EncryptedAttribute + +class AttributeValue(SamlBase): + """The saml:AttributeValue element""" + + c_tag = 'AttributeValue' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def attribute_value_from_string(xml_string): + """ Create AttributeValue instance from an XML string """ + return saml2.create_class_from_xml_string(AttributeValue, xml_string) + + +class Attribute(SamlBase): + """The saml:Attribute element""" + + c_tag = 'Attribute' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['Name'] = 'name' + c_attributes['NameFormat'] = 'name_format' + c_attributes['FriendlyName'] = 'friendly_name' + c_children['{%s}AttributeValue' % SAML_NAMESPACE] = ('attribute_value', + [AttributeValue]) + + def __init__(self, name=None, name_format=None, friendly_name=None, + attribute_value=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for Attribute + + :param name: Name attribute + :param name_format: NameFormat attribute + :param friendly_name: FriendlyName attribute + :param attribute_value: AttributeValue elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.name = name + self.name_format = name_format + self.friendly_name = friendly_name + self.attribute_value = attribute_value or [] + +def attribute_from_string(xml_string): + """ Create Attribute instance from an XML string """ + return saml2.create_class_from_xml_string(Attribute, xml_string) + + +class AttributeStatement(Statement): + """The saml:AttributeStatement element""" + + # TODO: EncryptedAttribute + c_tag = 'AttributeStatement' + c_namespace = SAML_NAMESPACE + c_children = Statement.c_children.copy() + c_attributes = Statement.c_attributes.copy() + c_children['{%s}Attribute' % SAML_NAMESPACE] = ('attribute', [Attribute]) + + def __init__(self, attribute=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for AttributeStatement + + :param attribute: Attribute elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + Statement.__init__(self, extension_elements, extension_attributes, + text) + self.attribute = attribute or [] + +def attribute_statement_from_string(xml_string): + """ Create AttributeStatement instance from an XML string """ + return saml2.create_class_from_xml_string(AttributeStatement, xml_string) + +# TODO: AuthzDecisionStatement + +class Action(SamlBase): + """The saml:Action element""" + + c_tag = 'Action' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['Namespace'] = 'namespace' + + def __init__(self, namespace=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for Action + + :param namespace: Namespace attribute + :param text: The text data in this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.namespace = namespace + +def action_from_string(xml_string): + """ Create Action instance from an XML string """ + return saml2.create_class_from_xml_string(Action, xml_string) + + +class SubjectConfirmationData(SamlBase): + """The saml:SubjectConfirmationData element""" + + c_tag = 'SubjectConfirmationData' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['NotBefore'] = 'not_before' + c_attributes['NotOnOrAfter'] = 'not_on_or_after' + c_attributes['Recipient'] = 'recipient' + c_attributes['InResponseTo'] = 'in_response_to' + c_attributes['Address'] = 'address' + + def __init__(self, not_before=None, not_on_or_after=None, recipient=None, + in_response_to=None, address=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for SubjectConfirmationData + + :param not_before: NotBefore attribute + :param not_on_or_after: NotOnOrAfter attribute + :param recipient: Recipient attribute + :param in_response_to: InResponseTo attribute + :param address: Address attribute + :param text: The text data in this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.not_before = not_before + self.not_on_or_after = not_on_or_after + self.recipient = recipient + self.in_response_to = in_response_to + self.address = address + +def subject_confirmation_data_from_string(xml_string): + """ Create SubjectConfirmationData instance from an XML string """ + return saml2.create_class_from_xml_string(SubjectConfirmationData, + xml_string) + + +class SubjectConfirmation(SamlBase): + """The saml:SubjectConfirmation element""" + # TODO: BaseID, EncryptedID element + + c_tag = 'SubjectConfirmation' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['Method'] = 'method' + c_children['{%s}NameID' % SAML_NAMESPACE] = ('name_id', NameID) + c_children['{%s}SubjectConfirmationData' % SAML_NAMESPACE] = ( + 'subject_confirmation_data', SubjectConfirmationData) + c_child_order = ['name_id', 'subject_confirmation_data'] + + def __init__(self, method=None, name_id=None, + subject_confirmation_data=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for SubjectConfirmation + + :param method: Method attribute + :param name_id: NameID element + :param subject_confirmation_data: SubjectConfirmationData element + :param text: The text data in this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.method = method + self.name_id = name_id + self.subject_confirmation_data = subject_confirmation_data + +def subject_confirmation_from_string(xml_string): + """ Create SubjectConfirmation instance from an XML string """ + return saml2.create_class_from_xml_string(SubjectConfirmation, xml_string) + + +class Subject(SamlBase): + """The saml:Subject element""" + # TODO: BaseID, EncryptedID element + + c_tag = 'Subject' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_children['{%s}NameID' % SAML_NAMESPACE] = ('name_id', NameID) + c_children['{%s}SubjectConfirmation' % SAML_NAMESPACE] = ( + 'subject_confirmation', [SubjectConfirmation]) + c_child_order = ['name_id', 'subject_confirmation'] + + def __init__(self, name_id=None, subject_confirmation=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for SubjectConfirmation + + :param name_id: NameID element + :param subject_confirmation: SubjectConfirmation element + :param text: The text data in this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.name_id = name_id + self.subject_confirmation = subject_confirmation or [] + +def subject_from_string(xml_string): + """ Create Subject instance from an XML string """ + return saml2.create_class_from_xml_string(Subject, xml_string) + + +class Condition(SamlBase): + """The saml:Condition element""" + + c_tag = 'Condition' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def condition_from_string(xml_string): + """ Create Condition instance from an XML string """ + return saml2.create_class_from_xml_string(Condition, xml_string) + + +class Audience(SamlBase): + """The saml:Audience element""" + + c_tag = 'Audience' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def audience_from_string(xml_string): + """ Create Audience instance from an XML string """ + return saml2.create_class_from_xml_string(Audience, xml_string) + + +class AudienceRestriction(Condition): + """The saml:AudienceRestriction element""" + + c_tag = 'AudienceRestriction' + c_namespace = SAML_NAMESPACE + c_children = Condition.c_children.copy() + c_attributes = Condition.c_attributes.copy() + c_children['{%s}Audience' % SAML_NAMESPACE] = ('audience', Audience) + + def __init__(self, text=None, audience=None, + extension_elements=None, extension_attributes=None): + """Constructor for AudienceRestriction + + :param text: The text data in this element + :param audience: Audience elements + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + Condition.__init__(self, extension_elements, extension_attributes, + text) + self.audience = audience + +def audience_restriction_from_string(xml_string): + """ Create AudienceRestriction instance from an XML string """ + return saml2.create_class_from_xml_string(AudienceRestriction, xml_string) + +class OneTimeUse(Condition): + """The saml:OneTimeUse element""" + + c_tag = 'OneTimeUse' + c_children = Condition.c_children.copy() + c_attributes = Condition.c_attributes.copy() + +def one_time_use_from_string(xml_string): + """ Create OneTimeUse instance from an XML string """ + return saml2.create_class_from_xml_string(OneTimeUse, xml_string) + + +class ProxyRestriction(Condition): + """The saml:Condition element""" + + c_tag = 'ProxyRestriction' + c_namespace = SAML_NAMESPACE + c_children = Condition.c_children.copy() + c_attributes = Condition.c_attributes.copy() + c_attributes['Count'] = 'count' + c_children['{%s}Audience' % SAML_NAMESPACE] = ('audience', [Audience]) + + def __init__(self, text=None, count=None, audience=None, + extension_elements=None, extension_attributes=None): + """Constructor for ProxyRestriction + + :param text: The text data in this element + :param count: Count attribute + :param audience: Audience elements + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + Condition.__init__(self, extension_elements, extension_attributes, + text) + self.count = count + self.audience = audience or [] + +def proxy_restriction_from_string(xml_string): + """ Create ProxyRestriction instance from an XML string """ + return saml2.create_class_from_xml_string(ProxyRestriction, xml_string) + + +class Conditions(SamlBase): + """The saml:Conditions element""" + + c_tag = 'Conditions' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['NotBefore'] = 'not_before' + c_attributes['NotOnOrAfter'] = 'not_on_or_after' + c_children['{%s}Condition' % SAML_NAMESPACE] = ('condition', [Condition]) + c_children['{%s}AudienceRestriction' % SAML_NAMESPACE] = ( + 'audience_restriction', [AudienceRestriction]) + c_children['{%s}OneTimeUse' % SAML_NAMESPACE] = ( + 'one_time_use', [OneTimeUse]) + c_children['{%s}ProxyRestriction' % SAML_NAMESPACE] = ( + 'proxy_restriction', [ProxyRestriction]) + c_child_order = ['condition', 'audience_restriction', 'one_time_use', + 'proxy_restriction'] + + def __init__(self, text=None, not_before=None, not_on_or_after=None, + condition=None, audience_restriction=None, + one_time_use=None, proxy_restriction=None, + extension_elements=None, extension_attributes=None): + """Constructor for ProxyRestriction + + :param text: The text data in this element + :param not_before: NotBefore attribute + :param not_on_or_after: NotOnOrAfter attribute + :param condition: Condition elements + :param audience_restriction: AudienceRestriction elements + :param one_time_use: OneTimeUse elements + :param proxy_restriction: ProxyRestriction elements + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.not_before = not_before + self.not_on_or_after = not_on_or_after + self.condition = condition or [] + self.audience_restriction = audience_restriction or [] + self.one_time_use = one_time_use or [] + self.proxy_restriction = proxy_restriction or [] + +def conditions_from_string(xml_string): + """ Create Conditions instance from an XML string """ + return saml2.create_class_from_xml_string(Conditions, xml_string) + + +class AssertionIDRef(SamlBase): + """The saml:AssertionIDRef element""" + c_tag = 'AssertionIDRef' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def assertion_id_ref_from_string(xml_string): + """ Create AssertionIDRef instance from an XML string """ + return saml2.create_class_from_xml_string(AssertionIDRef, xml_string) + + +class AssertionURIRef(SamlBase): + """The saml:AssertionURIRef element""" + c_tag = 'AssertionURIRef' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def assertion_uri_ref_from_string(xml_string): + """ Create AssertionURIRef instance from an XML string """ + return saml2.create_class_from_xml_string(AssertionURIRef, xml_string) + + +class Evidence(SamlBase): + """The saml:Evidence element""" + + c_tag = 'Evidence' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_children['{%s}AssertionIDRef' % SAML_NAMESPACE] = ('assertion_id_ref', + [AssertionIDRef]) + c_children['{%s}AssertionURIRef' % SAML_NAMESPACE] = ('assertion_uri_ref', + [AssertionURIRef]) + + def __init__(self, assertion_id_ref=None, assertion_uri_ref=None, + assertion=None, encrypted_assertion=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for Evidence + + :param assertion_id_ref: AssertionIDRef elements + :param assertion_uri_ref: AssertionURIRef elements + :param assertion: Assertion elements + :param encrypted_assertion: EncryptedAssertion elements + :param text: The text data in this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.assertion_id_ref = assertion_id_ref or [] + self.assertion_uri_ref = assertion_uri_ref or [] + self.assertion = assertion or [] + self.encrypted_assertion = encrypted_assertion or [] + +def evidence_from_string(xml_string): + """ Create Evidence instance from an XML string """ + return saml2.create_class_from_xml_string(Evidence, xml_string) + +class Advice(SamlBase): + """The saml:Advice element""" + + c_tag = 'Advice' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_children['{%s}AssertionIDRef' % SAML_NAMESPACE] = ('assertion_id_ref', + [AssertionIDRef]) + c_children['{%s}AssertionURIRef' % SAML_NAMESPACE] = ('assertion_uri_ref', + [AssertionURIRef]) + + def __init__(self, assertion_id_ref=None, assertion_uri_ref=None, + assertion=None, encrypted_assertion=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for Advice + + :param assertion_id_ref: AssertionIDRef elements + :param assertion_uri_ref: AssertionURIRef elements + :param assertion: Assertion elements + :param encrypted_assertion: EncryptedAssertion elements + :param text: The text data in this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.assertion_id_ref = assertion_id_ref or [] + self.assertion_uri_ref = assertion_uri_ref or [] + self.assertion = assertion or [] + self.encrypted_assertion = encrypted_assertion or [] + +def advice_from_string(xml_string): + """ Create Advice instance from an XML string """ + return saml2.create_class_from_xml_string(Advice, xml_string) + + +class Assertion(SamlBase): + """The saml:Assertion element""" + c_tag = 'Assertion' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['Version'] = 'version' + c_attributes['ID'] = 'identifier' + c_attributes['IssueInstant'] = 'issue_instant' + c_children['{%s}Issuer' % SAML_NAMESPACE] = ('issuer', Issuer) + c_children['{%s}Signature' % ds.DS_NAMESPACE] = ('signature', ds.Signature) + c_children['{%s}Subject' % SAML_NAMESPACE] = ('subject', Subject) + c_children['{%s}Conditions' % SAML_NAMESPACE] = ('conditions', Conditions) + c_children['{%s}Advice' % SAML_NAMESPACE] = ('advice', Advice) + c_children['{%s}Statement' % SAML_NAMESPACE] = ('statement', [Statement]) + c_children['{%s}AuthnStatement' % SAML_NAMESPACE] = ( + 'authn_statement', [AuthnStatement]) + c_children['{%s}AttributeStatement' % SAML_NAMESPACE] = ( + 'attribute_statement', [AttributeStatement]) + c_child_order = ['issuer', 'signature', 'subject', 'conditions', 'advice', + 'statement', 'authn_statement', 'authz_decision_statement', + 'attribute_statement'] + + def __init__(self, version=None, identifier=None, issue_instant=None, + issuer=None, signature=None, subject=None, conditions=None, + advice=None, statement=None, authn_statement=None, + authz_decision_statement=None, attribute_statement=None, + text=None, extension_elements=None, + extension_attributes=None): + """Constructor for Assertion + + :param version: Version attribute + :param identifier: ID attribute + :param issue_instant: IssueInstant attribute + :param issuer: Issuer element + :param signature: ds:Signature element + :param subject: Subject element + :param conditions: Conditions element + :param advice: Advice element + :param statement: Statement elements + :param authn_statement: AuthnStatement elements + :param authz_decision_statement: AuthzDecisionStatement elements + :param attribute_statement: AttributeStatement elements + :param text: The text data in this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.version = version + self.identifier = identifier + self.issue_instant = issue_instant + self.issuer = issuer + self.signature = signature + self.subject = subject + self.conditions = conditions + self.advice = advice + self.statement = statement or [] + self.authn_statement = authn_statement or [] + self.authz_decision_statement = authz_decision_statement or [] + self.attribute_statement = attribute_statement or [] + +def assertion_from_string(xml_string): + """ Create Assertion instance from an XML string """ + return saml2.create_class_from_xml_string(Assertion, xml_string) + +Evidence.c_children['{%s}Assertion' % SAML_NAMESPACE] = ( + 'assertion', [Assertion]) +Advice.c_children['{%s}Assertion' % SAML_NAMESPACE] = ( + 'assertion', [Assertion]) + + +class EncryptedID(SamlBase): + """The saml:EncryptedID element""" + c_tag = 'EncryptedID' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + + # TODO: This is just a skelton yet. + +def encrypted_id_from_string(xml_string): + """ Create EncryptedID instance from an XML string """ + return saml2.create_class_from_xml_string(EncryptedID, xml_string) + + +class EncryptedAssertion(SamlBase): + """The saml:EncryptedAssertion element""" + c_tag = 'EncryptedAssertion' + c_namespace = SAML_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + + # TODO: This is just a skelton yet. + +def encrypted_assertion_from_string(xml_string): + """ Create EncryptedAssertion instance from an XML string """ + return saml2.create_class_from_xml_string(EncryptedAssertion, xml_string) + +Evidence.c_children['{%s}EncryptedAssertion' % SAML_NAMESPACE] = ( + 'encrypted_assertion', [EncryptedAssertion]) +Advice.c_children['{%s}EncryptedAssertion' % SAML_NAMESPACE] = ( + 'encrypted_assertion', [EncryptedAssertion]) + +class AuthzDecisionStatement(Statement): + """The saml:AuthzDecisionStatement element""" + + c_tag = 'AuthzDecisionStatement' + c_namespace = SAML_NAMESPACE + c_children = Statement.c_children.copy() + c_attributes = Statement.c_attributes.copy() + + c_attributes['Resource'] = 'resource' + c_attributes['Decision'] = 'decision' + c_children['{%s}Action' % SAML_NAMESPACE] = ('action', [Action]) + c_children['{%s}Evidence' % SAML_NAMESPACE] = ('evidence', [Evidence]) + c_child_order = ['action', 'evidence'] + + def __init__(self, text=None, resource=None, decision=None, action=None, + evidence=None, extension_elements=None, + extension_attributes=None): + """Constructor for AuthzDecisionStatement + + :param text: str The text data in this element + :param resource: Resource attribute + :param decision: Decision attribute + :param action: Action Elements + :param evidence: Evidence Elements + :param extension_elements:A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + Statement.__init__(self, extension_elements, extension_attributes, + text) + self.resource = resource + self.decision = decision + self.action = action or [] + self.evidence = evidence or [] + +def authz_decision_statement_from_string(xml_string): + """ Create AuthzDecisionStatement instance from an XML string """ + return saml2.create_class_from_xml_string(AuthzDecisionStatement, + xml_string) + +Assertion.c_children['{%s}AuthzDecisionStatement' % SAML_NAMESPACE] = ( + 'authz_decision_statement', [AuthzDecisionStatement]) + diff --git a/src/saml2/samlp.py b/src/saml2/samlp.py new file mode 100644 index 0000000..13e6018 --- /dev/null +++ b/src/saml2/samlp.py @@ -0,0 +1,697 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Contains classes representing Samlp elements. + + Module objective: provide data classes for Samlp constructs. These + classes hide the XML-ness of Saml and provide a set of native Python + classes to interact with. + +""" + +from saml2 import saml, SamlBase, create_class_from_xml_string +import xmldsig as ds + +SAMLP_NAMESPACE = 'urn:oasis:names:tc:SAML:2.0:protocol' +SAMLP_TEMPLATE = '{urn:oasis:names:tc:SAML:2.0:protocol}%s' + +STATUS_SUCCESS = 'urn:oasis:names:tc:SAML:2.0:status:Success' +STATUS_REQUESTER = 'urn:oasis:names:tc:SAML:2.0:status:Requester' +STATUS_RESPONDER = 'urn:oasis:names:tc:SAML:2.0:status:Responder' +STATUS_VERSION_MISMATCH = 'urn:oasis:names:tc:SAML:2.0:status:VersionMismatch' + +STATUS_AUTHN_FAILED = 'urn:oasis:names:tc:SAML:2.0:status:AuthnFailed' +STATUS_INVALID_ATTR_NAME_OR_VALUE = ( + 'urn:oasis:names:tc:SAML:2.0:status:InvalidAttrNameOrValue') +STATUS_INVALID_NAMEID_POLICY = ( + 'urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy') +STATUS_NO_AUTHN_CONTEXT = 'urn:oasis:names:tc:SAML:2.0:status:NoAuthnContext' +STATUS_NO_AVAILABLE_IDP = 'urn:oasis:names:tc:SAML:2.0:status:NoAvailableIDP' +STATUS_NO_PASSIVE = 'urn:oasis:names:tc:SAML:2.0:status:NoPassive' +STATUS_NO_SUPPORTED_IDP = 'urn:oasis:names:tc:SAML:2.0:status:NoSupportedIDP' +STATUS_PARTIAL_LOGOUT = 'urn:oasis:names:tc:SAML:2.0:status:PartialLogout' +STATUS_PROXY_COUNT_EXCEEDED = ( + 'urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded') +STATUS_REQUEST_DENIED = 'urn:oasis:names:tc:SAML:2.0:status:RequestDenied' +STATUS_REQUEST_UNSUPPORTED = ( + 'urn:oasis:names:tc:SAML:2.0:status:RequestUnsupported') +STATUS_REQUEST_VERSION_DEPRECATED = ( + 'urn:oasis:names:tc:SAML:2.0:status:RequestVersionDeprecated') +STATUS_REQUEST_VERSION_TOO_HIGH = ( + 'urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooHigh') +STATUS_REQUEST_VERSION_TOO_LOW = ( + 'urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooLow') +STATUS_RESOURCE_NOT_RECOGNIZED = ( + 'urn:oasis:names:tc:SAML:2.0:status:ResourceNotRecognized') +STATUS_TOO_MANY_RESPONSES = ( + 'urn:oasis:names:tc:SAML:2.0:status:TooManyResponses') +STATUS_UNKNOWN_ATTR_PROFILE = ( + 'urn:oasis:names:tc:SAML:2.0:status:UnknownAttrProfile') +STATUS_UNKNOWN_PRINCIPAL = ( + 'urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal') +STATUS_UNSUPPORTED_BINDING = ( + 'urn:oasis:names:tc:SAML:2.0:status:UnsupportedBinding') + +class Extensions(SamlBase): + """The samlp:Extensions element""" + + c_tag = 'Extensions' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def extensions_from_string(xml_string): + """ Create Extensions instance from an XML string """ + return create_class_from_xml_string(Extensions, xml_string) + + +class AbstractRequest(SamlBase): + """The samlp:RequestAbstractType element""" + + c_tag = 'AbstractRequest' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['ID'] = 'identifier' + c_attributes['Version'] = 'version' + c_attributes['IssueInstant'] = 'issue_instant' + c_attributes['Destination'] = 'destination' + c_attributes['Consent'] = 'consent' + c_children['{%s}Issuer' % saml.SAML_NAMESPACE] = ('issuer', saml.Issuer) + c_children['{%s}Signature' % ds.DS_NAMESPACE] = ('signature', ds.Signature) + c_children['{%s}Extensions' % SAMLP_NAMESPACE] = ('extensions', Extensions) + c_child_order = ['issuer', 'signature', 'extensions'] + + def __init__(self, identifier=None, version=None, issue_instant=None, + destination=None, consent=None, issuer=None, signature=None, + extensions=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for AbstractRequest + + :param identifier: ID attribute + :param version: Version attribute + :param issue_instant: IssueInstant attribute + :param destination: Destination attribute + :param consent: Consent attribute + :param issuer: Issuer element + :param signature: Signature element + :param extensions: Extensions element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.identifier = identifier + self.version = version + self.issue_instant = issue_instant + self.destination = destination + self.consent = consent + self.issuer = issuer + self.signature = signature + self.extensions = extensions + +def abstract_request_from_string(xml_string): + """ Create AbstractRequest instance from an XML string """ + return create_class_from_xml_string(AbstractRequest, xml_string) + +class StatusDetail(SamlBase): + """The samlp:StatusDetail element""" + c_tag = 'StatusDetail' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def status_detail_from_string(xml_string): + """ Create StatusDetail instance from an XML string """ + return create_class_from_xml_string(StatusDetail, xml_string) + +class StatusMessage(SamlBase): + """The samlp:StatusMessage element""" + c_tag = 'StatusMessage' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def status_message_from_string(xml_string): + """ Create StatusMessage instance from an XML string """ + return create_class_from_xml_string(StatusMessage, xml_string) + +class StatusCode(SamlBase): + """The samlp:StatusCode element""" + c_tag = 'StatusCode' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['Value'] = 'value' + + def __init__(self, value=None, status_code=None, + text=None, extension_elements=None, extension_attributes=None): + """Constructor for Status + + :param value: Value attribute + :param status_code: StatusCode element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.value = value + self.status_code = status_code + +def status_code_from_string(xml_string): + """ Create StatusCode instance from an XML string """ + return create_class_from_xml_string(StatusCode, xml_string) + +StatusCode.c_children['{%s}StatusCode' % SAMLP_NAMESPACE] = ( + 'status_code', StatusCode) + + +class Status(SamlBase): + """The samlp:Status element""" + + c_tag = 'Status' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_children['{%s}StatusCode' % SAMLP_NAMESPACE] = ('status_code', StatusCode) + c_children['{%s}StatusMessage' % SAMLP_NAMESPACE] = ( + 'status_message', StatusMessage) + c_children['{%s}StatusDetail' % SAMLP_NAMESPACE] = ( + 'status_detail', StatusDetail) + c_child_order = ['status_code', 'status_message', 'status_detail'] + + def __init__(self, status_code=None, status_message=None, + status_detail=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for Status + + :param status_code: StatusCode element + :param status_message: StatusMessage element + :param status_detail: StatusDetail element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.status_code = status_code + self.status_message = status_message + self.status_detail = status_detail + +def status_from_string(xml_string): + """ Create Status instance from an XML string """ + return create_class_from_xml_string(Status, xml_string) + + +class StatusResponse(SamlBase): + """The samlp:StatusResponse element""" + + c_tag = 'StatusResponse' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['ID'] = 'identifier' + c_attributes['InResponseTo'] = 'in_response_to' + c_attributes['Version'] = 'version' + c_attributes['IssueInstant'] = 'issue_instant' + c_attributes['Destination'] = 'destination' + c_attributes['Consent'] = 'consent' + c_children['{%s}Issuer' % saml.SAML_NAMESPACE] = ('issuer', saml.Issuer) + c_children['{%s}Signature' % ds.DS_NAMESPACE] = ('signature', ds.Signature) + c_children['{%s}Extensions' % SAMLP_NAMESPACE] = ('extensions', Extensions) + c_children['{%s}Status' % SAMLP_NAMESPACE] = ('status', Status) + c_child_order = ['issuer', 'signature', 'extensions', 'status'] + + def __init__(self, identifier=None, in_response_to=None, version=None, + issue_instant=None, destination=None, consent=None, + issuer=None, signature=None, extensions=None, status=None, + text=None, extension_elements=None, extension_attributes=None): + """Constructor for StatusResponse + + :param identifier: ID attribute + :param in_respones_to: InResponseTo attribute + :param version: Version attribute + :param issue_instant: IssueInstant attribute + :param destination: Destination attribute + :param consent: Consent attribute + :param issuer: Issuer element + :param signature: Signature element + :param extensions: Extensions element + :param status: Status element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.identifier = identifier + self.in_response_to = in_response_to + self.version = version + self.issue_instant = issue_instant + self.destination = destination + self.consent = consent + self.issuer = issuer + self.signature = signature + self.extensions = extensions + self.status = status + +def status_response_from_string(xml_string): + """ Create StatusResponse instance from an XML string """ + return create_class_from_xml_string(StatusResponse, xml_string) + + +class Response(StatusResponse): + """The samlp:Response element""" + + c_tag = 'Response' + c_namespace = SAMLP_NAMESPACE + c_children = StatusResponse.c_children.copy() + c_attributes = StatusResponse.c_attributes.copy() + c_children['{%s}Assertion' % saml.SAML_NAMESPACE] = ( + 'assertion', [saml.Assertion]) + c_children['{%s}EncryptedAssertion' % saml.SAML_NAMESPACE] = ( + 'encrypted_assertion', [saml.EncryptedAssertion]) + c_child_order = ['issuer', 'signature', 'extensions', 'status', 'assertion', + 'encrypted_assertion'] + + def __init__(self, identifier=None, in_response_to=None, version=None, + issue_instant=None, destination=None, consent=None, + issuer=None, signature=None, extensions=None, status=None, + assertion=None, encrypted_assertion=None, + text=None, extension_elements=None, extension_attributes=None): + """Constructor for Response + + :param identifier: ID attribute + :param in_respones_to: InResponseTo attribute + :param version: Version attribute + :param issue_instant: IssueInstant attribute + :param destination: Destination attribute + :param consent: Consent attribute + :param issuer: Issuer element + :param signature: Signature element + :param extensions: Extensions element + :param status: Status element + :param assertion: Assertion elements + :param encrypted_assertion: EncryptedAssertion elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + StatusResponse.__init__(self, identifier, in_response_to, + version, issue_instant, + destination, consent, + issuer, signature, + extensions, status, text, + extension_elements, extension_attributes) + self.assertion = assertion or [] + self.encrypted_assertion = encrypted_assertion or [] + +def response_from_string(xml_string): + """ Create Response instance from an XML string """ + return create_class_from_xml_string(Response, xml_string) + + +class NameIDPolicy(SamlBase): + """The samlp:NameIDPolicy element""" + + c_tag = 'NameIDPolicy' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['Format'] = 'form' + c_attributes['SPNameQualifier'] = 'sp_name_qualifier' + c_attributes['AllowCreate'] = 'allow_create' + + def __init__(self, form=None, sp_name_qualifier=None, allow_create=None, + text=None, extension_elements=None, extension_attributes=None): + """Constructor for NameIDPolicy + + :param form: Format attribute + :param sp_name_qualifier: SPNameQualifier attribute + :param allow_create: AllowCreate attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.form = form + self.sp_name_qualifier = sp_name_qualifier + self.allow_create = allow_create + +def name_id_policy_from_string(xml_string): + """ Create NameIDPolicy instance from an XML string """ + return create_class_from_xml_string(NameIDPolicy, xml_string) + + +class IDPEntry(SamlBase): + """The samlp:IDPEntry element""" + + c_tag = 'IDPEntry' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['ProviderID'] = 'provider_id' + c_attributes['Name'] = 'name' + c_attributes['Loc'] = 'loc' + + def __init__(self, provider_id=None, name=None, loc=None, + text=None, extension_elements=None, extension_attributes=None): + """Constructor for IDPEntry + + :param provider_id: ProviderID attribute + :param name: Name attribute + :param loc: Loc attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.provider_id = provider_id + self.name = name + self.loc = loc + +def idp_entry_from_string(xml_string): + """ Create IDPEntry instance from an XML string """ + return create_class_from_xml_string(IDPEntry, xml_string) + + +class GetComplete(SamlBase): + """The samlp:GetComplete element""" + + c_tag = 'GetComplete' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def get_complete_from_string(xml_string): + """ Create GetComplete instance from an XML string """ + return create_class_from_xml_string(GetComplete, xml_string) + + +class IDPList(SamlBase): + """The samlp:IDPList element""" + + c_tag = 'IDPList' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_children['{%s}IDPEntry' % SAMLP_NAMESPACE] = ('idp_entry', [IDPEntry]) + c_children['{%s}GetComplete' % SAMLP_NAMESPACE] = ( + 'get_complete', GetComplete) + c_child_order = ['idp_entry', 'get_complete'] + + def __init__(self, idp_entry=None, get_complete=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for IDPList + + :param idp_entry: IDPEntry elements + :param get_complete: GetComplete element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.idp_entry = idp_entry or [] + self.get_complete = get_complete + +def idp_list_from_string(xml_string): + """ Create IDPList instance from an XML string """ + return create_class_from_xml_string(IDPList, xml_string) + + +class RequesterID(SamlBase): + """The samlp:RequesterID element""" + c_tag = 'RequesterID' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def requester_id_from_string(xml_string): + """ Create RequesterID instance from an XML string """ + return create_class_from_xml_string(RequesterID, xml_string) + + +class Scoping(SamlBase): + """The samlp:Scoping element""" + + c_tag = 'Scoping' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['ProxyCount'] = 'proxy_count' + c_children['{%s}IDPList' % SAMLP_NAMESPACE] = ('idp_list', IDPList) + c_children['{%s}RequesterID' % SAMLP_NAMESPACE] = ( + 'requester_id', [RequesterID]) + c_child_order = ['idp_list', 'requester_id'] + + def __init__(self, proxy_count=None, idp_list=None, requester_id=None, + text=None, extension_elements=None, extension_attributes=None): + """Constructor for Scoping + + :param proxy_count: ProxyCount attribute + :param idp_list: IDPList element + :param requester_id: list A list of RequesterID instances + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.proxy_count = proxy_count + self.idp_list = idp_list + self.requester_id = requester_id or [] + +def scoping_from_string(xml_string): + """ Create Scoping instance from an XML string """ + return create_class_from_xml_string(Scoping, xml_string) + + +class RequestedAuthnContext(SamlBase): + """The samlp:RequestedAuthnContext element""" + + c_tag = 'RequestedAuthnContext' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + c_attributes['Comparison'] = 'comparison' + c_children['{%s}AuthnContextClassRef' % saml.SAML_NAMESPACE] = ( + 'authn_context_class_ref', [saml.AuthnContextClassRef]) + c_children['{%s}AuthnContextDeclRef' % saml.SAML_NAMESPACE] = ( + 'authn_context_decl_ref', [saml.AuthnContextDeclRef]) + + def __init__(self, comparison=None, authn_context_class_ref=None, + authn_context_decl_ref=None, + text=None, extension_elements=None, extension_attributes=None): + """Constructor for RequestedAuthnContext + + :param comparison: Comparison attribute + :param authn_context_class_ref: list A list of AuthnContextClassRef instances + :param authn_context_decl_ref: list A list of AuthnContextDeclRef instances + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + SamlBase.__init__(self, text, extension_elements, extension_attributes) + self.comparison = comparison + self.authn_context_class_ref = authn_context_class_ref or [] + self.authn_context_decl_ref = authn_context_decl_ref or [] + +def requested_authn_context_from_string(xml_string): + """ Create RequestedAuthnContext instance from an XML string """ + return create_class_from_xml_string(RequestedAuthnContext, xml_string) + + +class AuthnRequest(AbstractRequest): + """The samlp:AuthnRequest element""" + + c_tag = 'AuthnRequest' + c_namespace = SAMLP_NAMESPACE + c_children = AbstractRequest.c_children.copy() + c_attributes = AbstractRequest.c_attributes.copy() + c_attributes['ForceAuthn'] = 'force_authn' + c_attributes['IsPassive'] = 'is_passive' + c_attributes['AssertionConsumerServiceIndex'] = \ + 'assertion_consumer_service_index' + c_attributes['AssertionConsumerServiceURL'] = \ + 'assertion_consumer_service_url' + c_attributes['ProtocolBinding'] = 'protocol_binding' + c_attributes['AssertionConsumingServiceIndex'] = \ + 'assertion_consuming_service_index' + c_attributes['ProviderName'] = 'provider_name' + c_children['{%s}Subject' % saml.SAML_NAMESPACE] = ('subject', saml.Subject) + c_children['{%s}NameIDPolicy' % SAMLP_NAMESPACE] = ( + 'name_id_policy', NameIDPolicy) + c_children['{%s}Conditions' % saml.SAML_NAMESPACE] = ( + 'conditions', saml.Conditions) + c_children['{%s}RequestedAuthnContext' % SAMLP_NAMESPACE] = ( + 'requested_authn_context', RequestedAuthnContext) + c_children['{%s}Scoping' % SAMLP_NAMESPACE] = ('scoping', Scoping) + c_child_order = ['issuer', 'signature', 'extensions', 'subject', + 'name_id_policy', 'conditions', 'requested_authn_context', + 'scoping'] + + def __init__(self, identifier=None, version=None, issue_instant=None, + destination=None, consent=None, issuer=None, signature=None, + extensions=None, subject=None, name_id_policy=None, + conditions=None, requested_authn_context=None, scoping=None, + force_authn=None, is_passive=None, + assertion_consumer_service_index=None, + assertion_consumer_service_url=None, + protocol_binding=None, assertion_consuming_service_index=None, + provider_name=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for AuthnRequest + + :param identifier: ID attribute + :param version: Version attribute + :param issue_instant: IssueInstant attribute + :param destination: Destination attribute + :param consent: Consent attribute + :param issuer: Issuer element + :param signature: Signature element + :param extensions: Extensions element + :param subject: Subject element + :param name_id_policy: NameIDPolicy element + :param conditions: Conditions element + :param requested_authn_context: RequestedAuthnContext element + :param scoping: Scoping element + :param force_authn: ForceAuthn attribute + :param is_passive: IsPassive attribute + :param assertion_consumer_service_index: AssertionConsumerServiceIndex + element + :param assertion_consumer_service_url: AssertionConsumerServiceURL + element + :param protocol_binding: ProtocolBinding element + :param assertion_consuming_service_index: + AssertionConsumingServiceIndex element + :param provider_name: ProviderName element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + AbstractRequest.__init__(self, identifier, version, issue_instant, + destination, consent, issuer, signature, + extensions, text, extension_elements, + extension_attributes) + self.subject = subject + self.name_id_policy = name_id_policy + self.conditions = conditions + self.requested_authn_context = requested_authn_context + self.conditions = conditions + self.requested_authn_context = requested_authn_context + self.scoping = scoping + self.force_authn = force_authn + self.is_passive = is_passive + self.assertion_consumer_service_index = assertion_consumer_service_index + self.assertion_consumer_service_url = assertion_consumer_service_url + self.protocol_binding = protocol_binding + self.assertion_consuming_service_index = \ + assertion_consuming_service_index + self.provider_name = provider_name + +def authn_request_from_string(xml_string): + """ Create AuthnRequest instance from an XML string """ + return create_class_from_xml_string(AuthnRequest, xml_string) + + +class SessionIndex(SamlBase): + """The samlp:SessionIndex element""" + c_tag = 'SessionIndex' + c_namespace = SAMLP_NAMESPACE + c_children = SamlBase.c_children.copy() + c_attributes = SamlBase.c_attributes.copy() + +def session_index_from_string(xml_string): + """ Create SessionIndex instance from an XML string """ + return create_class_from_xml_string(SessionIndex, xml_string) + + +class LogoutRequest(AbstractRequest): + """The samlp:LogoutRequest element""" + + c_tag = 'LogoutRequest' + c_namespace = SAMLP_NAMESPACE + c_children = AbstractRequest.c_children.copy() + c_attributes = AbstractRequest.c_attributes.copy() + c_attributes['NotOnOrAfter'] = 'not_on_or_after' + c_attributes['Reason'] = 'reason' + c_children['{%s}BaseID' % saml.SAML_NAMESPACE] = ('base_id', saml.BaseID) + c_children['{%s}NameID' % saml.SAML_NAMESPACE] = ('name_id', saml.NameID) + c_children['{%s}EncryptedID' % saml.SAML_NAMESPACE] = ( + 'encrypted_id', saml.EncryptedID) + c_children['{%s}SessionIndex' % SAMLP_NAMESPACE] = ( + 'session_index', SessionIndex) + c_child_order = ['issuer', 'signature', 'extensions', 'base_id', 'name_id', + 'encrypted_id', 'session_index'] + + def __init__(self, identifier=None, version=None, issue_instant=None, + destination=None, consent=None, issuer=None, signature=None, + extensions=None, not_on_or_after=None, reason=None, + base_id=None, name_id=None, encrypted_id=None, + session_index=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for LogoutRequest + + :param identifier: ID attribute + :param version: Version attribute + :param issue_instant: IssueInstant attribute + :param destination: Destination attribute + :param consent: Consent attribute + :param issuer: Issuer element + :param signature: Signature element + :param extensions: Extensions element + :param not_on_or_after: NotOnOrAfter attribute + :param reason: Reason attribute + :param base_id: BaseID element + :param name_id: NameID element + :param encrypted_id: EncryptedID element + :param session_index: SessionIndex element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + AbstractRequest.__init__(self, identifier, version, issue_instant, + destination, consent, issuer, signature, + extensions, text, extension_elements, + extension_attributes) + self.not_on_or_after = not_on_or_after + self.reason = reason + self.base_id = base_id + self.name_id = name_id + self.encrypted_id = encrypted_id + self.session_index = session_index + +def logout_request_from_string(xml_string): + """ Create LogoutRequest instance from an XML string """ + return create_class_from_xml_string(LogoutRequest, xml_string) + + +class LogoutResponse(StatusResponse): + """The samlp:LogoutResponse element""" + + c_tag = 'LogoutResponse' + c_namespace = SAMLP_NAMESPACE + c_children = StatusResponse.c_children.copy() + c_attributes = StatusResponse.c_attributes.copy() + +def logout_response_from_string(xml_string): + """ Create LogoutResponse instance from an XML string """ + return create_class_from_xml_string(LogoutResponse, xml_string) diff --git a/src/saml2/samlp_test_data.py b/src/saml2/samlp_test_data.py new file mode 100644 index 0000000..9258fe8 --- /dev/null +++ b/src/saml2/samlp_test_data.py @@ -0,0 +1,454 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Test data for saml2""" + +__author__ = 'tmatsuo@sios.com (Takashi MATSUO)' + +TEST_STATUS_CODE = """ + + + +""" + +TEST_STATUS = """ + + + + + status message + + +""" + +TEST_NAME_ID_POLICY = """ + +""" + +TEST_IDP_ENTRY = """ + +""" + +TEST_IDP_LIST = """ + + + http://www.sios.com/GetComplete + +""" + +TEST_SCOPING = """ + + + + http://www.sios.com/GetComplete + + http://www.sios.com/RequesterID + +""" + +TEST_REQUESTED_AUTHN_CONTEXT = """ + + + http://www.sios.com/authnContextClassRef + + + http://www.sios.com/authnContextDeclRef + + +""" + +TEST_AUTHN_REQUEST = """ + + + http://www.sios.com/test + + + + + + + 8 + + + + + xpath + + + xpath + + + + digest value + + + + signature value + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + V2VkIEp1biAgNCAxMjoxMTowMyBFRFQgMjAwMwo + +
+ + + + tmatsuo@sios.com + + + + admin@sios.com + + + + + + + + + + + http://www.sios.com/Audience + + + + + http://www.sios.com/Audience + + + + + http://www.sios.com/authnContextClassRef + + + http://www.sios.com/authnContextDeclRef + + + + + + http://www.sios.com/GetComplete + + http://www.sios.com/RequesterID + +
+""" + +TEST_LOGOUT_REQUEST = """ + + + http://www.sios.com/test + + + + + + + 8 + + + + + xpath + + + xpath + + + + digest value + + + + signature value + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + V2VkIEp1biAgNCAxMjoxMTowMyBFRFQgMjAwMwo + +
+ + + tmatsuo@sios.com + + + tmatsuo@sios.com + + + session index +
+""" + +TEST_LOGOUT_RESPONSE = """ + + + http://www.sios.com/test + + + + + + + 8 + + + + + xpath + + + xpath + + + + digest value + + + + signature value + + + + key name + + + +

p

+ q + g + y + j + seed + pgen counter +
+
+ + + + xpath + + + xpath + + + + + + issuer name + 1 + + x509 ski + x509 subject name + x509 certificate + x509 crl + + + pgp key id + pgp key packet + + + mgmt data + + + spki sexp + spki sexp2 + +
+ + V2VkIEp1biAgNCAxMjoxMTowMyBFRFQgMjAwMwo + +
+ + + + + + status message + + +
+""" diff --git a/src/saml2/test_base.py b/src/saml2/test_base.py new file mode 100644 index 0000000..88a41eb --- /dev/null +++ b/src/saml2/test_base.py @@ -0,0 +1,62 @@ + +import saml2 +from saml2 import SamlBase + +DS_NAMESPACE = 'http://www.w3.org/2000/09/xmldsig#' + +class Foo(SamlBase): + etag = "Foo" + enamespace = DS_NAMESPACE + + def __init__(self, extension_elements=None, extension_attributes=None, + text=None): + SamlBase.__init__(self, extension_elements, extension_attributes, text) + +def cmplist(list0,list1): + return set(list0) == set(list1) + +class TestBase: + def test_init(self): + b = saml2.SamlBase() + assert b._attributes == {} + assert cmplist(b.__dict__.keys(), ['extension_attributes', '_children', + 'text', '_attributes', 'etag', + 'enamespace', '_child_order', 'extension_elements']) + assert b.text == None + assert b.etag == '' + assert b.enamespace == '' + assert b._attributes == {} + assert b._children == {} + assert b._child_order == [] + assert b.extension_attributes == {} + assert b.extension_elements == [] + + def test_init_attr(self): + b = saml2.SamlBase() + b._init_attribute('Id','identifier',"urn:mace:example.org:foo#bar") + assert b._attributes == {'Id': 'identifier'} + assert b.identifier == 'urn:mace:example.org:foo#bar' + assert b.text == None + assert b.etag == '' + assert b.enamespace == '' + assert b._children == {} + assert b._child_order == [] + assert b.extension_attributes == {} + assert b.extension_elements == [] + + def test_init_child(self): + b = saml2.SamlBase() + xml_name = '{%s}Foo' % DS_NAMESPACE + b._init_child(xml_name, 'foo', [Foo], []) + + assert b.text == None + assert b.etag == '' + assert b.enamespace == '' + assert b._attributes == {} + assert b._children.has_key(xml_name) + assert b._children[xml_name] == ("foo", [Foo]) + assert b._child_order == [] + assert b.extension_attributes == {} + assert b.extension_elements == [] + + \ No newline at end of file diff --git a/src/saml2/test_data.py b/src/saml2/test_data.py new file mode 100644 index 0000000..fcfe91d --- /dev/null +++ b/src/saml2/test_data.py @@ -0,0 +1,227 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Test data for saml2""" + +__author__ = 'tmatsuo@sios.com (Takashi MATSUO)' + +TEST_NAME_ID = """ + + tmatsuo@sios.com + +""" + +TEST_ISSUER = """ + + http://www.sios.com/test + +""" + +TEST_SUBJECT_LOCALITY = """ + +""" + +TEST_AUTHN_CONTEXT_CLASS_REF = """ + + http://www.sios.com/authnContextClassRef + +""" + +TEST_AUTHN_CONTEXT_DECL_REF = """ + + http://www.sios.com/authnContextDeclRef + +""" + +TEST_AUTHN_CONTEXT_DECL = """ + + http://www.sios.com/authnContextDecl + +""" + +TEST_AUTHENTICATING_AUTHORITY = """ + + http://www.sios.com/authenticatingAuthority + +""" + +TEST_AUTHN_CONTEXT = """ + + urn:oasis:names:tc:SAML:2.0:ac:classes:Password + +""" + +TEST_AUTHN_STATEMENT = """ + + + urn:oasis:names:tc:SAML:2.0:ac:classes:Password + + +""" + +TEST_ATTRIBUTE_VALUE = """ +value for test attribute +""" + +TEST_ATTRIBUTE = """ + + value1 of test attribute + value2 of test attribute + +""" + +TEST_ATTRIBUTE_STATEMENT = """ + + + value1 of test attribute + value2 of test attribute + + + value1 of test attribute2 + value2 of test attribute2 + + +""" + +TEST_SUBJECT_CONFIRMATION_DATA = """ + + +""" + +TEST_SUBJECT_CONFIRMATION = """ + + + tmatsuo@sios.com + + + + +""" + +TEST_SUBJECT = """ + + + tmatsuo@sios.com + + + + admin@sios.com + + + + + +""" + +TEST_CONDITION = """ + +""" + +TEST_AUDIENCE = """ + + http://www.sios.com/Audience + +""" + +TEST_AUDIENCE_RESTRICTION = """ + + + http://www.sios.com/Audience + + +""" + +TEST_ONE_TIME_USE = """ + +""" + +TEST_PROXY_RESTRICTION = """ + + http://www.sios.com/Audience + +""" + +TEST_CONDITIONS = """ + + + + + http://www.sios.com/Audience + + + + + http://www.sios.com/Audience + + +""" + +TEST_ASSERTION_ID_REF = """ + + zzlieajngjbkjggjldmgindkckkolcblndbghlhm + +""" + +TEST_ASSERTION_URI_REF = """ + + http://www.sios.com/AssertionURIRef + +""" + +TEST_ACTION = """ + +""" + diff --git a/src/saml2/test_utils.py b/src/saml2/test_utils.py new file mode 100644 index 0000000..fcf0dcf --- /dev/null +++ b/src/saml2/test_utils.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +import string +import time +from saml2 import utils + +def test_id(): + oid = utils.create_id() + print oid + assert len(oid) == 40 + for c in oid: + assert c in string.lowercase + +def test_get_date_and_time_now(): + dt = utils.get_date_and_time() + # Should return something similar to 2009-07-09T10:24:28Z + print dt + assert isinstance(dt,basestring) + assert len(dt) == 20 + +def test_get_date_and_time_old(): + t = time.struct_time((2009, 7, 9, 10, 39, 36, 3, 190,0)) + dt = utils.get_date_and_time(time.mktime(t)) + print dt + assert isinstance(dt,basestring) + assert len(dt) == 20 + assert dt == "2009-07-09T09:39:36Z" + +def test_lib_init(): + utils.lib_init() \ No newline at end of file diff --git a/src/saml2/test_x_metadata.py b/src/saml2/test_x_metadata.py new file mode 100644 index 0000000..391664f --- /dev/null +++ b/src/saml2/test_x_metadata.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python + +try: + from xml.etree import ElementTree +except ImportError: + from elementtree import ElementTree +import saml2 +from saml2 import saml, samlp, md +import xmldsig as ds +import base64 + +def _verify_contact_person(person): + assert person.contact_type == "technical" + assert person.given_name.text == "Roland" + assert person.sur_name.text == "Hedberg" + assert person.email_address[0].text == "roland.hedberg@adm.umu.se" + +def _verify_contact_person(person): + assert person.contact_type == "technical" + assert person.given_name.text == "Roland" + assert person.sur_name.text == "Hedberg" + assert person.email_address[0].text == "roland.hedberg@adm.umu.se" + +def _verify_single_sign_on_service(sso): + assert sso.binding == "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + assert sso.location == "http://xenosmilus.umdc.umu.se/simplesaml/saml2/idp/SSOService.php" + +def _verify_single_logout_service(sso): + assert sso.binding == "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + assert sso.location == "http://xenosmilus.umdc.umu.se/simplesaml/saml2/idp/SingleLogoutService.php" + +def _get_keys(key_descriptors): + res = {} + for kd in key_descriptors: + use = kd.use + coded_key = kd.key_info.x509_data[0].x509_certificate[0].text + key = base64.b64decode(coded_key) + try: + res[use].append(key) + except KeyError: + res[use] = [key] + return res + + +def _verify_idp_sso_description(idpssodesc): + for ssoserv in idpssodesc.single_sign_on_service: # only one + _verify_single_sign_on_service(ssoserv) + for sloserv in idpssodesc.single_logout_service: # only one + _verify_single_logout_service(sloserv) + assert idpssodesc.name_id_format[0].text == "urn:oasis:names:tc:SAML:2.0:nameid-format:transient" + assert len(idpssodesc.key_descriptor) == 2 + keys = _get_keys(idpssodesc.key_descriptor) + assert set(keys.keys()) == set(["signing","encryption"]) + # one key for signing and one for encryption + assert len(keys["signing"]) == 1 + assert len(keys["encryption"]) == 1 + +def test_contactdata(contact): + person = md.contact_person_from_string(contact) + _verify_contact_person(person) + +def test_entity_descriptor(idp_metadata): + ed = md.entity_descriptor_from_string(idp_metadata) + assert ed.entity_id == "http://xenosmilus.umdc.umu.se/simplesaml/saml2/idp/metadata.php" + contact_person = ed.contact_person[0] + _verify_contact_person(contact_person) + idpsso = ed.idp_sso_descriptor[0] + _verify_idp_sso_description(idpsso) + assert ed.entity_id == "http://xenosmilus.umdc.umu.se/simplesaml/saml2/idp/metadata.php" + print ed.to_string() + # all other attributes are supposed to be None,'',[] or {} + for key,val in ed.__dict__.items(): + if key in ["contact_person", "idp_sso_descriptor", "entity_id"]: + continue + else: + if isinstance(val,basestring): + val = val.strip('\t\r\n ') + assert val in [None,'',[],{}] + +# def test_idp_metadata(idp_metadata): +# entities_descriptor = md.entities_descriptor_from_string(idp_metadata) +# print type(idp_metadata) +# print idp_metadata +# print entities_descriptor.to_string() +# assert False + \ No newline at end of file diff --git a/src/saml2/utils.py b/src/saml2/utils.py new file mode 100644 index 0000000..86fc470 --- /dev/null +++ b/src/saml2/utils.py @@ -0,0 +1,206 @@ +#!/opt/local/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Contains utility methods used with SAML-2.""" + +import saml2 +import libxml2 +import xmlsec +import random +import time + +# TODO: write tests for these methods + +def create_id(): + ret = "" + for _ in range(40): + ret = ret + chr(random.randint(0, 15) + ord('a')) + return ret + +def get_date_and_time(base=None): + if base is None: + base = time.time() + return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(base)) + +def lib_init(): + # Init libxml library + libxml2.initParser() + libxml2.substituteEntitiesDefault(1) + + # Init xmlsec library + if xmlsec.init() < 0: + raise(saml2.Error("Error: xmlsec initialization failed.")) + + # Check loaded library version + if xmlsec.checkVersion() != 1: + raise(saml2.Error( + "Error: loaded xmlsec library version is not compatible.\n")) + + # Init crypto library + if xmlsec.cryptoAppInit(None) < 0: + raise(saml2.Error("Error: crypto initialization failed.")) + + # Init xmlsec-crypto library + if xmlsec.cryptoInit() < 0: + raise(saml2.Error("Error: xmlsec-crypto initialization failed.")) + +def lib_shutdown(): + # Shutdown xmlsec-crypto library + xmlsec.cryptoShutdown() + + # Shutdown crypto library + xmlsec.cryptoAppShutdown() + + # Shutdown xmlsec library + xmlsec.shutdown() + + # Shutdown LibXML2 + libxml2.cleanupParser() + +def verify(xml, key_file): + lib_init() + ret = verify_xml(xml, key_file) + lib_shutdown() + return ret == 0 + +# Verifies XML signature in xml_file using public key from key_file. +# Returns 0 on success or a negative value if an error occurs. +def verify_xml(xml, key_file): + + doc = libxml2.parseDoc(xml) + if doc is None or doc.getRootElement() is None: + cleanup(doc) + raise saml2.Error("Error: unable to parse file \"%s\"" % xml) + + # Find start node + node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, + xmlsec.DSigNs) + + # Create signature context, we don't need keys manager in this example + dsig_ctx = xmlsec.DSigCtx() + if dsig_ctx is None: + cleanup(doc) + raise saml2.Error("Error: failed to create signature context") + + # Load public key, assuming that there is not password + if key_file.endswith(".der"): + key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatDer, + None, None, None) + else: + key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatPem, + None, None, None) + + if key is None: + cleanup(doc, dsig_ctx) + raise saml2.Error( + "Error: failed to load public key from \"%s\"" % key_file) + + dsig_ctx.signKey = key + + # Set key name to the file name, this is just an example! + if key.setName(key_file) < 0: + cleanup(doc, dsig_ctx) + raise saml2.Error( + "Error: failed to set key name for key from \"%s\"" % key_file) + + # Verify signature + if dsig_ctx.verify(node) < 0: + cleanup(doc, dsig_ctx) + raise saml2.Error("Error: signature verify") + + # Print verification result to stdout + if dsig_ctx.status == xmlsec.DSigStatusSucceeded: + ret = 0 + else: + ret = -1 + + # Success + cleanup(doc, dsig_ctx) + return ret + +def sign(xml, key_file, cert_file=None): + lib_init() + ret = sign_xml(xml, key_file, cert_file) + lib_shutdown() + return ret + +# Signs the xml_file using private key from key_file and dynamicaly +# created enveloped signature template. +# Returns 0 on success or a negative value if an error occurs. +def sign_xml(xml, key_file, cert_file=None): + + # Load template + doc = libxml2.parseDoc(xml) + if doc is None or doc.getRootElement() is None: + cleanup(doc) + raise saml2.Error("Error: unable to parse string \"%s\"" % xml) + + node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, + xmlsec.DSigNs) + + if node is None: + cleanup(doc) + raise saml2.Error("Error: start node not found.") + + # Create signature context, we don't need keys manager in this example + dsig_ctx = xmlsec.DSigCtx() + if dsig_ctx is None: + cleanup(doc) + raise saml2.Error("Error: failed to create signature context") + + # Load private key, assuming that there is not password + key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatPem, + None, None, None) + if key is None: + cleanup(doc, dsig_ctx) + raise saml2.Error( + "Error: failed to load private pem key from \"%s\"" % key_file) + dsig_ctx.signKey = key + + if cert_file is not None: + if xmlsec.cryptoAppKeyCertLoad( + dsig_ctx.signKey, cert_file, xmlsec.KeyDataFormatPem) < 0: + cleanup(doc, dsig_ctx) + raise saml2.Error( + "Error: failed to load cert pem from \"%s\"" % cert_file) + else: + pass + + # Set key name to the file name, this is just an example! + if key.setName(key_file) < 0: + cleanup(doc, dsig_ctx) + raise saml2.Error( + "Error: failed to set key name for key from \"%s\"" % key_file) + + # Sign the template + if dsig_ctx.sign(node) < 0: + cleanup(doc, dsig_ctx) + raise saml2.Error("Error: signature failed") + + # signed document to string + ret = doc.__str__() + + # Success + cleanup(doc, dsig_ctx, 1) + + return ret + +def cleanup(doc=None, dsig_ctx=None, res=-1): + if dsig_ctx is not None: + dsig_ctx.destroy() + if doc is not None: + doc.freeDoc() + return res diff --git a/src/xmldsig/__init__.py b/src/xmldsig/__init__.py new file mode 100644 index 0000000..ff10984 --- /dev/null +++ b/src/xmldsig/__init__.py @@ -0,0 +1,1058 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Contains classes representing xmldsig elements. + + Module objective: provide data classes for xmldsig constructs. These + classes hide the XML-ness of Saml and provide a set of native Python + classes to interact with. + + Classes in this module inherits saml.SamlBase now. + +""" + +try: + from xml.etree import cElementTree as ElementTree +except ImportError: + try: + import cElementTree as ElementTree + except ImportError: + from elementtree import ElementTree +import saml2 +from saml2 import create_class_from_xml_string + +DS_NAMESPACE = 'http://www.w3.org/2000/09/xmldsig#' +DS_TEMPLATE = '{http://www.w3.org/2000/09/xmldsig#}%s' + +ENCODING_BASE64 = 'http://www.w3.org/2000/09/xmldsig#base64' +DIGEST_SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1' +ALG_EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#' +SIG_DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1' +SIG_RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1' +MAC_SHA1 = 'http://www.w3.org/2000/09/xmldsig#hmac-sha1' + +C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315' +C14N_WITH_C = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments' + +TRANSFORM_XSLT = 'http://www.w3.org/TR/1999/REC-xslt-19991116' +TRANSFORM_XPATH = 'http://www.w3.org/TR/1999/REC-xpath-19991116' +TRANSFORM_ENVELOPED = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature' + + +class DsBase(saml2.SamlBase): + """The ds:DsBase element""" + + c_children = {} + c_attributes = {} + +class Object(DsBase): + """The ds:Object element""" + + c_tag = 'Object' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_attributes['Id'] = 'identifier' + c_attributes['MimeType'] = 'mime_type' + c_attributes['Encoding'] = 'encoding' + + def __init__(self, identifier=None, mime_type=None, encoding=None, + text=None, extension_elements=None, extension_attributes=None): + """Constructor for Object + + :param identifier: Id attribute + :param mime_type: MimeType attribute + :param encoding: Encoding attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.identifier = identifier + self.mime_type = mime_type + self.encoding = encoding + +def object_from_string(xml_string): + """ Create Object instance from an XML string """ + return create_class_from_xml_string(Object, xml_string) + +class MgmtData(DsBase): + """The ds:MgmtData element""" + + c_tag = 'MgmtData' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def mgmt_data_from_string(xml_string): + """ Create MgmtData instance from an XML string """ + return create_class_from_xml_string(MgmtData, xml_string) + + +class SPKISexp(DsBase): + """The ds:SPKISexp element""" + + c_tag = 'SPKISexp' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def spki_sexp_from_string(xml_string): + """ Create SPKISexp instance from an XML string """ + return create_class_from_xml_string(SPKISexp, xml_string) + + +class SPKIData(DsBase): + """The ds:SPKIData element""" + + c_tag = 'SPKIData' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_children['{%s}SPKISexp' % DS_NAMESPACE] = ('spki_sexp', [SPKISexp]) + + def __init__(self, spki_sexp=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for SPKIData + + :param spki_sexp: SPKISexp elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.spki_sexp = spki_sexp or [] + +def spki_data_from_string(xml_string): + """ Create SPKIData instance from an XML string """ + return create_class_from_xml_string(SPKIData, xml_string) + + +class PGPKeyID(DsBase): + """The ds:PGPKeyID element""" + + c_tag = 'PGPKeyID' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def pgp_key_id_from_string(xml_string): + """ Create PGPKeyID instance from an XML string """ + return create_class_from_xml_string(PGPKeyID, xml_string) + + +class PGPKeyPacket(DsBase): + """The ds:PGPKeyPacket element""" + + c_tag = 'PGPKeyPacket' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def pgp_key_packet_from_string(xml_string): + """ Create PGPKeyPacket instance from an XML string """ + return create_class_from_xml_string(PGPKeyPacket, xml_string) + + +class PGPData(DsBase): + """The ds:PGPData element""" + + c_tag = 'PGPData' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_children['{%s}PGPKeyID' % DS_NAMESPACE] = ('pgp_key_id', PGPKeyID) + c_children['{%s}PGPKeyPacket' % DS_NAMESPACE] = ( + 'pgp_key_packet', PGPKeyPacket) + c_child_order = ['pgp_key_id', 'pgp_key_packet'] + + def __init__(self, pgp_key_id=None, pgp_key_packet=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for PGPKeyINfo + + :param pgp_key_id: PGPKeyID element + :param pgp_key_packet: PGPKeyPacket element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.pgp_key_id = pgp_key_id + self.pgp_key_packet = pgp_key_packet + +def pgp_data_from_string(xml_string): + """ Create PGPData instance from an XML string """ + return create_class_from_xml_string(PGPData, xml_string) + + +class X509IssuerName(DsBase): + """The ds:X509IssuerName element""" + + c_tag = 'X509IssuerName' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def x509_issuer_name_from_string(xml_string): + """ Create X509IssuerName instance from an XML string """ + return create_class_from_xml_string(X509IssuerName, xml_string) + + +class X509IssuerNumber(DsBase): + """The ds:X509IssuerNumber element""" + + c_tag = 'X509IssuerNumber' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def x509_issuer_number_from_string(xml_string): + """ Create X509IssuerNumber instance from an XML string """ + return create_class_from_xml_string(X509IssuerNumber, xml_string) + + +class X509IssuerSerial(DsBase): + """The ds:X509IssuerSerial element""" + + c_tag = 'X509IssuerSerial' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_children['{%s}X509IssuerName' % DS_NAMESPACE] = ( + 'x509_issuer_name', X509IssuerName) + c_children['{%s}X509IssuerNumber' % DS_NAMESPACE] = ( + 'x509_issuer_number', X509IssuerNumber) + c_child_order = ['x509_issuer_name', 'x509_issuer_number'] + + def __init__(self, x509_issuer_name=None, x509_issuer_number=None, + text=None, extension_elements=None, extension_attributes=None): + """Constructor for X509IssuerSerial + + :param x509_issuer_name: X509IssuerName + :param x509_issuer_number: X509IssuerNumber + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.x509_issuer_name = x509_issuer_name + self.x509_issuer_number = x509_issuer_number + + +def x509_issuer_serial_from_string(xml_string): + """ Create X509IssuerSerial instance from an XML string """ + return create_class_from_xml_string(X509IssuerSerial, xml_string) + + +class X509SKI(DsBase): + """The ds:X509SKI element""" + + c_tag = 'X509SKI' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def x509_ski_from_string(xml_string): + """ Create X509SKI instance from an XML string """ + return create_class_from_xml_string(X509SKI, xml_string) + + +class X509SubjectName(DsBase): + """The ds:X509SubjectName element""" + + c_tag = 'X509SubjectName' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def x509_subject_name_from_string(xml_string): + """ Create X509SubjectName instance from an XML string """ + return create_class_from_xml_string(X509SubjectName, xml_string) + + +class X509Certificate(DsBase): + """The ds:X509Certificate element""" + + c_tag = 'X509Certificate' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def x509_certificate_from_string(xml_string): + """ Create X509Certificate instance from an XML string """ + return create_class_from_xml_string(X509Certificate, xml_string) + + +class X509CRL(DsBase): + """The ds:X509CRL element""" + + c_tag = 'X509CRL' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def x509_crl_from_string(xml_string): + """ Create X509CRL instance from an XML string """ + return create_class_from_xml_string(X509CRL, xml_string) + + +class X509Data(DsBase): + """The ds:X509Data element""" + + c_tag = 'X509Data' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_children['{%s}X509IssuerSerial' % DS_NAMESPACE] = ( + 'x509_issuer_serial', [X509IssuerSerial]) + c_children['{%s}X509SKI' % DS_NAMESPACE] = ('x509_ski', [X509SKI]) + c_children['{%s}X509SubjectName' % DS_NAMESPACE] = ( + 'x509_subject_name', [X509SubjectName]) + c_children['{%s}X509Certificate' % DS_NAMESPACE] = ( + 'x509_certificate', [X509Certificate]) + c_children['{%s}X509CRL' % DS_NAMESPACE] = ('x509_crl', [X509CRL]) + c_child_order = ['x509_issuer_serial', 'x509_ski', 'x509_subject_name', + 'x509_certificate', 'x509_crl'] + + def __init__(self, x509_issuer_serial=None, x509_ski=None, + x509_subject_name=None, x509_certificate=None, x509_crl=None, + text=None, extension_elements=None, extension_attributes=None): + """Constructor for X509Data + + :param x509_issuer_serial: X509IssuerSerial element + :param x509_ski: X509SKI element + :param x509_subject_name: X509SubjectName element + :param x509_certificate: X509Certificate element + :param x509_crl: X509CRL element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string + pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.x509_issuer_serial = x509_issuer_serial or [] + self.x509_ski = x509_ski or [] + self.x509_subject_name = x509_subject_name or [] + self.x509_certificate = x509_certificate or [] + self.x509_crl = x509_crl or [] + + +def x509_data_from_string(xml_string): + """ Create X509Data instance from an XML string """ + return create_class_from_xml_string(X509Data, xml_string) + + +class XPath(DsBase): + """The ds:XPath element""" + + c_tag = 'XPath' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def x_path_from_string(xml_string): + """ Create XPath instance from an XML string """ + return create_class_from_xml_string(XPath, xml_string) + + +class Transform(DsBase): + """The ds:Transform element""" + + c_tag = 'Transform' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_attributes['Algorithm'] = 'algorithm' + c_children['{%s}XPath' % DS_NAMESPACE] = ('xpath', [XPath]) + + def __init__(self, xpath=None, algorithm=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for Transform + + :param xpath: XPath elements + :param algorithm: Algorithm attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.xpath = xpath or [] + self.algorithm = algorithm + +def transform_from_string(xml_string): + """ Create Transform instance from an XML string """ + return create_class_from_xml_string(Transform, xml_string) + + +class Transforms(DsBase): + """The ds:Transforms element""" + + c_tag = 'Transforms' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_children['{%s}Transform' % DS_NAMESPACE] = ('transform', [Transform]) + + def __init__(self, transform=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for Transforms + + :param transform: Transform elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.transform = transform or [] + +def transforms_from_string(xml_string): + """ Create Transforms instance from an XML string """ + return create_class_from_xml_string(Transforms, xml_string) + + +class RetrievalMethod(DsBase): + """The ds:RetrievalMethod element""" + + c_tag = 'RetrievalMethod' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_attributes['URI'] = 'uri' + c_attributes['Type'] = 'typ' + c_children['{%s}Transforms' % DS_NAMESPACE] = ('transforms', [Transforms]) + + def __init__(self, transforms=None, uri=None, typ=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for RetrievalMethod + + :param transforms: Transforms elements + :param uri: URI attribute + :param typ: Type attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.transforms = transforms or [] + self.uri = uri + self.typ = typ + +def retrieval_method_from_string(xml_string): + """ Create RetrievalMethod instance from an XML string """ + return create_class_from_xml_string(RetrievalMethod, xml_string) + + +class Modulus(DsBase): + """The ds:Modulus element""" + + c_tag = 'Modulus' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def modulus_from_string(xml_string): + """ Create Modulus instance from an XML string """ + return create_class_from_xml_string(Modulus, xml_string) + + +class Exponent(DsBase): + """The ds:Exponent element""" + + c_tag = 'Exponent' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def exponent_from_string(xml_string): + """ Create Exponent instance from an XML string """ + return create_class_from_xml_string(Exponent, xml_string) + + +class RSAKeyValue(DsBase): + """The ds:RSAKeyValue element""" + + c_tag = 'RSAKeyValue' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_children['{%s}Modulus' % DS_NAMESPACE] = ('modulus', Modulus) + c_children['{%s}Exponent' % DS_NAMESPACE] = ('exponent', Exponent) + c_child_order = ['modulus', 'exponent'] + + def __init__(self, modulus=None, exponent=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for RSAKeyValue + + :param modulus: Modulus element + :param exponent: Exponent element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.modulus = modulus + self.exponent = exponent + +def rsa_key_value_from_string(xml_string): + """ Create RSAKeyValue instance from an XML string """ + return create_class_from_xml_string(RSAKeyValue, xml_string) + + +class DsP(DsBase): + """The ds:P element""" + + c_tag = 'P' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def p_from_string(xml_string): + """ Create DsP instance from an XML string """ + return create_class_from_xml_string(DsP, xml_string) + + +class DsQ(DsBase): + """The ds:Q element""" + + c_tag = 'Q' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def q_from_string(xml_string): + """ Create DsQ instance from an XML string """ + return create_class_from_xml_string(DsQ, xml_string) + + +class DsG(DsBase): + """The ds:G element""" + + c_tag = 'G' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def g_from_string(xml_string): + """ Create DsG instance from an XML string """ + return create_class_from_xml_string(DsG, xml_string) + + +class DsY(DsBase): + """The ds:Y element""" + + c_tag = 'Y' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def y_from_string(xml_string): + """ Create DsY instance from an XML string """ + return create_class_from_xml_string(DsY, xml_string) + + +class DsJ(DsBase): + """The ds:J element""" + + c_tag = 'J' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def j_from_string(xml_string): + """ Create DsJ instance from an XML string """ + return create_class_from_xml_string(DsJ, xml_string) + + +class Seed(DsBase): + """The ds:Seed element""" + + c_tag = 'Seed' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def seed_from_string(xml_string): + """ Create Seed instance from an XML string """ + return create_class_from_xml_string(Seed, xml_string) + + +class PgenCounter(DsBase): + """The ds:PgenCounter element""" + + c_tag = 'PgenCounter' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def pgen_counter_from_string(xml_string): + """ Create PgenCounter instance from an XML string """ + return create_class_from_xml_string(PgenCounter, xml_string) + + +class DSAKeyValue(DsBase): + """The ds:DSAKeyValue element""" + + c_tag = 'DSAKeyValue' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_children['{%s}P' % DS_NAMESPACE] = ('p', DsP) + c_children['{%s}Q' % DS_NAMESPACE] = ('q', DsQ) + c_children['{%s}G' % DS_NAMESPACE] = ('g', DsG) + c_children['{%s}Y' % DS_NAMESPACE] = ('y', DsY) + c_children['{%s}J' % DS_NAMESPACE] = ('j', DsJ) + c_children['{%s}Seed' % DS_NAMESPACE] = ('seed', Seed) + c_children['{%s}PgenCounter' % DS_NAMESPACE] = ('pgen_counter', PgenCounter) + + c_child_order = ['p', 'q', 'g', 'y', 'j', 'seed', 'pgen_counter'] + + def __init__(self, p=None, q=None, g=None, y=None, j=None, seed=None, + pgen_counter=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for DSAKeyValue + + :param p: P element + :param q: Q element + :param g: G element + :param y: Y element + :param j: J element + :param seed: Seed element + :param pgen_counter: PgenCounter element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.p = p + self.q = q + self.g = g + self.y = y + self.j = j + self.seed = Seed + self.pgen_counter = pgen_counter + +def dsa_key_value_from_string(xml_string): + """ Create DSAKeyValue instance from an XML string """ + return create_class_from_xml_string(DSAKeyValue, xml_string) + + +class KeyValue(DsBase): + """The ds:KeyValue element""" + + c_tag = 'KeyValue' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_children['{%s}RSAKeyValue' % DS_NAMESPACE] = ('rsa_key_value', + RSAKeyValue) + c_children['{%s}DSAKeyValue' % DS_NAMESPACE] = ('dsa_key_value', + DSAKeyValue) + + c_child_order = ['rsa_key_value', 'dsa_key_value'] + + def __init__(self, rsa_key_value=None, dsa_key_value=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for DSAKeyValue + + :param rsa_key_value: RSAKeyValue element + :param dsa_key_value: DSAKeyValue element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.rsa_key_value = rsa_key_value + self.dsa_key_value = dsa_key_value + +def key_value_from_string(xml_string): + """ Create KeyValue instance from an XML string """ + return create_class_from_xml_string(KeyValue, xml_string) + + +class KeyName(DsBase): + """The ds:KeyName element""" + + c_tag = 'KeyName' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def key_name_from_string(xml_string): + """ Create KeyName instance from an XML string """ + return create_class_from_xml_string(KeyName, xml_string) + + +class KeyInfo(DsBase): + """The ds:KeyInfo element""" + + c_tag = 'KeyInfo' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_attributes['Id'] = "identifier" + c_children['{%s}KeyName' % DS_NAMESPACE] = ('key_name', [KeyName]) + c_children['{%s}KeyValue' % DS_NAMESPACE] = ('key_value', [KeyValue]) + c_children['{%s}RetrievalMethod' % DS_NAMESPACE] = ( + 'retrieval_method', [RetrievalMethod]) + c_children['{%s}X509Data' % DS_NAMESPACE] = ('x509_data', [X509Data]) + c_children['{%s}PGPData' % DS_NAMESPACE] = ('pgp_data', [PGPData]) + c_children['{%s}SPKIData' % DS_NAMESPACE] = ('spki_data', [SPKIData]) + c_children['{%s}MgmtData' % DS_NAMESPACE] = ('mgmt_data', [MgmtData]) + + c_child_order = ['key_name', 'key_value', 'retrieval_method', 'x509_data', + 'pgp_data', 'spki_data', 'mgmt_data'] + + def __init__(self, key_name=None, key_value=None, retrieval_method=None, + x509_data=None, pgp_data=None, spki_data=None, mgmt_data=None, + identifier=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for DSAKeyValue + + :param key_name: KeyName elements + :param key_value: KeyValue elements + :param retrieval_method: RetrievalMethod elements + :param x509_data: X509Data elements + :param pgp_data: PGPData elements + :param spki_data: SPKIData elements + :param mgmt_data: MgmtData elements + :param identifier: Id attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.key_name = key_name or [] + self.key_value = key_value or [] + self.retrieval_method = retrieval_method or [] + self.x509_data = x509_data or [] + self.pgp_data = pgp_data or [] + self.spki_data = spki_data or [] + self.mgmt_data = mgmt_data or [] + self.identifier = identifier + +def key_info_from_string(xml_string): + """ Create KeyInfo instance from an XML string """ + return create_class_from_xml_string(KeyInfo, xml_string) + + +class DigestValue(DsBase): + """The ds:DigestValue element""" + + c_tag = 'DigestValue' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def digest_value_from_string(xml_string): + """ Create DigestValue instance from an XML string """ + return create_class_from_xml_string(DigestValue, xml_string) + + +class DigestMethod(DsBase): + """The ds:DigestMethod element""" + + c_tag = 'DigestMethod' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_attributes['Algorithm'] = "algorithm" + + def __init__(self, algorithm=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for DigestMethod + + :param algorithm: Algorithm attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.algorithm = algorithm + +def digest_method_from_string(xml_string): + """ Create DigestMethod instance from an XML string """ + return create_class_from_xml_string(DigestMethod, xml_string) + + +class Reference(DsBase): + """The ds:Reference element""" + + c_tag = 'Reference' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_attributes['Id'] = "identifier" + c_attributes['URI'] = "uri" + c_attributes['Type'] = "type" + c_children['{%s}Transforms' % DS_NAMESPACE] = ('transforms', [Transforms]) + c_children['{%s}DigestMethod' % DS_NAMESPACE] = ( + 'digest_method', [DigestMethod]) + c_children['{%s}DigestValue' % DS_NAMESPACE] = ('digest_value', + [DigestValue]) + c_child_order = ['transforms', 'digest_method', 'digest_value'] + + def __init__(self, identifier=None, uri=None, typ=None, transforms=None, + digest_method=None, digest_value=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for Reference + + Args: + :param identifier: Id attribute + :param uri: URI attribute + :param type: Type attribute + :param transforms: Transforms elements + :param digest_method: DigestMethod elements + :param digest_value: DigestValue elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.identifier = identifier + self.uri = uri + self.type = typ + self.transforms = transforms or [] + self.digest_method = digest_method or [] + self.digest_value = digest_value or [] + +def reference_from_string(xml_string): + """ Create Reference instance from an XML string """ + return create_class_from_xml_string(Reference, xml_string) + + +class HMACOutputLength(DsBase): + """The ds:HMACOutputLength element""" + + c_tag = 'HMACOutputLength' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + +def hmac_output_length_from_string(xml_string): + """ Create HMACOutputLength instance from an XML string """ + return create_class_from_xml_string(HMACOutputLength, xml_string) + + +class SignatureMethod(DsBase): + """The ds:SignatureMethod element""" + + c_tag = 'SignatureMethod' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_attributes['Algorithm'] = "algorithm" + c_children['{%s}HMACOutputLength' % DS_NAMESPACE] = ( + 'hmac_output_length', HMACOutputLength) + + def __init__(self, algorithm=None, hmac_output_length=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for SignatureMethod + + :param algorighm: Algorithm attribute + :param hmac_output_length: HMACOutputLength element + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.algorithm = algorithm + self.hmac_output_length = hmac_output_length + +def signature_method_from_string(xml_string): + """ Create SignatureMethod instance from an XML string """ + return create_class_from_xml_string(SignatureMethod, xml_string) + + +class CanonicalizationMethod(DsBase): + """The ds:CanonicalizationMethod element""" + + c_tag = 'CanonicalizationMethod' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_attributes['Algorithm'] = "algorithm" + + def __init__(self, algorithm=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for CanonicalizationMethod + + :param algorighm: Algorithm attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.algorithm = algorithm + +def canonicalization_method_from_string(xml_string): + """ Create CanonicalizationMethod instance from an XML string """ + return create_class_from_xml_string(CanonicalizationMethod, xml_string) + + +class SignedInfo(DsBase): + """The ds:SignedInfo element""" + + c_tag = 'SignedInfo' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_attributes['Id'] = "identifier" + c_children['{%s}CanonicalizationMethod' % DS_NAMESPACE] = ( + 'canonicalization_method', CanonicalizationMethod) + c_children['{%s}SignatureMethod' % DS_NAMESPACE] = ( + 'signature_method', SignatureMethod) + c_children['{%s}Reference' % DS_NAMESPACE] = ('reference', [Reference]) + c_child_order = ['canonicalization_method', 'signature_method', + 'reference'] + + def __init__(self, identifier=None, canonicalization_method=None, + signature_method=None, reference=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for SignedInfo + + :param identifier: Id attribute + :param canonicalization_method: CanonicalizationMethod element + :param signature_method: SignatureMethod element + :param reference: Reference elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.identifier = identifier + self.canonicalization_method = canonicalization_method + self.signature_method = signature_method + self.reference = reference or [] + +def signed_info_from_string(xml_string): + """ Create SignedInfo instance from an XML string """ + return create_class_from_xml_string(SignedInfo, xml_string) + + +class SignatureValue(DsBase): + """The ds:SignatureValue element""" + + c_tag = 'SignatureValue' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_attributes['Id'] = "identifier" + + def __init__(self, identifier=None, text=None, extension_elements=None, + extension_attributes=None): + """Constructor for SignatureValue + + Args: + :param identifier: Id attribute + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.identifier = identifier + +def signature_value_from_string(xml_string): + """ Create SignatureValue instance from an XML string """ + return create_class_from_xml_string(SignatureValue, xml_string) + + +class Signature(DsBase): + """The ds:Signature element""" + + c_tag = 'Signature' + c_namespace = DS_NAMESPACE + c_children = DsBase.c_children.copy() + c_attributes = DsBase.c_attributes.copy() + c_attributes['Id'] = "identifier" + c_children['{%s}SignedInfo' % DS_NAMESPACE] = ('signed_info', SignedInfo) + c_children['{%s}SignatureValue' % DS_NAMESPACE] = ( + 'signature_value', SignatureValue) + c_children['{%s}KeyInfo' % DS_NAMESPACE] = ('key_info', KeyInfo) + c_children['{%s}Object' % DS_NAMESPACE] = ('object', [Object]) + c_child_order = ["signed_info", "signature_value", "key_info", "object"] + + def __init__(self, identifier=None, signed_info=None, signature_value=None, + key_info=None, objects=None, text=None, + extension_elements=None, extension_attributes=None): + """Constructor for Signature + + :param identifier: Id attribute + :param signed_info: SignedInfo element + :param signature_value: SignatureValue element + :param key_info: KeyInfo element + :param object: Object elements + :param text: The text data in the this element + :param extension_elements: A list of ExtensionElement instances + :param extension_attributes: A dictionary of attribute value string pairs + """ + + DsBase.__init__(self, text, extension_elements, extension_attributes) + self.identifier = identifier + self.signed_info = signed_info + self.signature_value = signature_value + self.key_info = key_info + self.object = objects or [] + + +def signature_from_string(xml_string): + """ Create Signature instance from an XML string """ + return create_class_from_xml_string(Signature, xml_string) + + +def get_empty_signature(canonicalization_method_algorithm=C14N_WITH_C, + signature_method_algorithm=SIG_RSA_SHA1, + transform_algorithm=TRANSFORM_ENVELOPED, + digest_algorithm=DIGEST_SHA1): + + canonicalization_method = CanonicalizationMethod( + algorithm=canonicalization_method_algorithm) + signature_method = SignatureMethod(algorithm=signature_method_algorithm) + transforms = Transforms(transform=Transform(algorithm=transform_algorithm)) + digest_method = DigestMethod(algorithm=digest_algorithm) + reference = Reference(uri="", transforms=transforms, + digest_method=digest_method, + digest_value=DigestValue()) + signed_info = SignedInfo( + canonicalization_method=canonicalization_method, + signature_method=signature_method, + reference=reference) + signature = Signature(signed_info=signed_info, + signature_value=SignatureValue(), + key_info=KeyInfo(key_value=KeyValue())) + return signature + diff --git a/tests/ds_test.py b/tests/ds_test.py new file mode 100644 index 0000000..36dca52 --- /dev/null +++ b/tests/ds_test.py @@ -0,0 +1,655 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for saml2.saml""" + +__author__ = 'tmatsuo@sios.com (Takashi MATSUO)' + +import unittest +try: + from xml.etree import ElementTree +except ImportError: + from elementtree import ElementTree +from saml2 import ds_test_data +import xmldsig as ds + +class ObjectTest(unittest.TestCase): + + def setUp(self): + self.object = ds.Object() + + def testAccessors(self): + """Test for Object accessors""" + self.object.id = "object_id" + self.object.mime_type = "test/plain; charset=UTF-8" + self.object.encoding = ds.ENCODING_BASE64 + new_object = ds.ObjectFromString(self.object.ToString()) + self.assert_(new_object.id == "object_id") + self.assert_(new_object.mime_type == "test/plain; charset=UTF-8") + self.assert_(new_object.encoding == ds.ENCODING_BASE64) + + def testUsingTestData(self): + """Test for ObjectFromString() using test data""" + new_object = ds.ObjectFromString(ds_test_data.TEST_OBJECT) + self.assert_(new_object.id == "object_id") + self.assert_(new_object.encoding == ds.ENCODING_BASE64) + self.assert_(new_object.text.strip() == + "V2VkIEp1biAgNCAxMjoxMTowMyBFRFQgMjAwMwo") + + +class MgmtDataTest(unittest.TestCase): + + def setUp(self): + self.mgmt_data = ds.MgmtData() + + def testAccessors(self): + """Test for MgmtData accessors""" + self.mgmt_data.text = "mgmt data" + new_mgmt_data = ds.MgmtDataFromString(self.mgmt_data.ToString()) + self.assert_(new_mgmt_data.text.strip() == "mgmt data") + + def testUsingTestData(self): + """Test for MgmtDataFromString() using test data""" + new_mgmt_data = ds.MgmtDataFromString(ds_test_data.TEST_MGMT_DATA) + self.assert_(new_mgmt_data.text.strip() == "mgmt data") + + +class SPKISexpTest(unittest.TestCase): + + def setUp(self): + self.spki_sexp = ds.SPKISexp() + + def testAccessors(self): + """Test for SPKISexp accessors""" + self.spki_sexp.text = "spki sexp" + new_spki_sexp = ds.SPKISexpFromString(self.spki_sexp.ToString()) + self.assert_(new_spki_sexp.text.strip() == "spki sexp") + + def testUsingTestData(self): + """Test for SPKISexpFromString() using test data""" + new_spki_sexp = ds.SPKISexpFromString(ds_test_data.TEST_SPKI_SEXP) + self.assert_(new_spki_sexp.text.strip() == "spki sexp") + + +class SPKIDataTest(unittest.TestCase): + + def setUp(self): + self.spki_data = ds.SPKIData() + + def testAccessors(self): + """Test for SPKIData accessors""" + self.spki_data.spki_sexp.append( + ds.SPKISexpFromString(ds_test_data.TEST_SPKI_SEXP)) + new_spki_data = ds.SPKIDataFromString(self.spki_data.ToString()) + self.assert_(new_spki_data.spki_sexp[0].text.strip() == "spki sexp") + + def testUsingTestData(self): + """Test for SPKIDataFromString() using test data""" + new_spki_data = ds.SPKIDataFromString(ds_test_data.TEST_SPKI_DATA) + self.assert_(new_spki_data.spki_sexp[0].text.strip() == "spki sexp") + self.assert_(new_spki_data.spki_sexp[1].text.strip() == "spki sexp2") + + +class PGPDataTest(unittest.TestCase): + + def setUp(self): + self.pgp_data = ds.PGPData() + + def testAccessors(self): + """Test for PGPData accessors""" + self.pgp_data.pgp_key_id = ds.PGPKeyID(text="pgp key id") + self.pgp_data.pgp_key_packet = ds.PGPKeyPacket(text="pgp key packet") + new_pgp_data = ds.PGPDataFromString(self.pgp_data.ToString()) + self.assert_(isinstance(new_pgp_data.pgp_key_id, ds.PGPKeyID)) + self.assert_(isinstance(new_pgp_data.pgp_key_packet, ds.PGPKeyPacket)) + self.assert_(new_pgp_data.pgp_key_id.text.strip() == "pgp key id") + self.assert_(new_pgp_data.pgp_key_packet.text.strip() == "pgp key packet") + + def testUsingTestData(self): + """Test for PGPDataFromString() using test data""" + new_pgp_data = ds.PGPDataFromString(ds_test_data.TEST_PGP_DATA) + self.assert_(isinstance(new_pgp_data.pgp_key_id, ds.PGPKeyID)) + self.assert_(isinstance(new_pgp_data.pgp_key_packet, ds.PGPKeyPacket)) + self.assert_(new_pgp_data.pgp_key_id.text.strip() == "pgp key id") + self.assert_(new_pgp_data.pgp_key_packet.text.strip() == "pgp key packet") + + +class X509IssuerSerialTest(unittest.TestCase): + + def setUp(self): + self.x509_issuer_serial = ds.X509IssuerSerial() + + def testAccessors(self): + """Test for X509IssuerSerial accessors""" + self.x509_issuer_serial.x509_issuer_name = ds.X509IssuerName( + text="issuer name") + self.x509_issuer_serial.x509_issuer_number = ds.X509IssuerNumber(text="1") + new_x509_issuer_serial = ds.X509IssuerSerialFromString( + self.x509_issuer_serial.ToString()) + self.assert_(new_x509_issuer_serial.x509_issuer_name.text.strip() == + "issuer name") + self.assert_(new_x509_issuer_serial.x509_issuer_number.text.strip() == "1") + + def testUsingTestData(self): + """Test for X509IssuerSerialFromString() using test data""" + new_x509_issuer_serial = ds.X509IssuerSerialFromString( + ds_test_data.TEST_X509_ISSUER_SERIAL) + self.assert_(new_x509_issuer_serial.x509_issuer_name.text.strip() == + "issuer name") + self.assert_(new_x509_issuer_serial.x509_issuer_number.text.strip() == "1") + + +class X509DataTest(unittest.TestCase): + + def setUp(self): + self.x509_data = ds.X509Data() + + def testAccessors(self): + """Test for X509Data accessors""" + self.x509_data.x509_issuer_serial.append(ds.X509IssuerSerialFromString( + ds_test_data.TEST_X509_ISSUER_SERIAL)) + self.x509_data.x509_ski.append(ds.X509SKI(text="x509 ski")) + self.x509_data.x509_subject_name.append(ds.X509SubjectName( + text="x509 subject name")) + self.x509_data.x509_certificate.append(ds.X509Certificate( + text="x509 certificate")) + self.x509_data.x509_crl.append(ds.X509CRL(text="x509 crl")) + new_x509_data = ds.X509DataFromString(self.x509_data.ToString()) + self.assert_(isinstance(new_x509_data.x509_issuer_serial[0], + ds.X509IssuerSerial)) + self.assert_(new_x509_data.x509_ski[0].text.strip() == "x509 ski") + self.assert_(isinstance(new_x509_data.x509_ski[0], ds.X509SKI)) + self.assert_(new_x509_data.x509_subject_name[0].text.strip() == + "x509 subject name") + self.assert_(isinstance(new_x509_data.x509_subject_name[0], + ds.X509SubjectName)) + self.assert_(new_x509_data.x509_certificate[0].text.strip() == + "x509 certificate") + self.assert_(isinstance(new_x509_data.x509_certificate[0], + ds.X509Certificate)) + self.assert_(new_x509_data.x509_crl[0].text.strip() == "x509 crl") + self.assert_(isinstance(new_x509_data.x509_crl[0],ds.X509CRL)) + + def testUsingTestData(self): + """Test for X509DataFromString() using test data""" + new_x509_data = ds.X509DataFromString(ds_test_data.TEST_X509_DATA) + self.assert_(isinstance(new_x509_data.x509_issuer_serial[0], + ds.X509IssuerSerial)) + self.assert_(new_x509_data.x509_ski[0].text.strip() == "x509 ski") + self.assert_(isinstance(new_x509_data.x509_ski[0], ds.X509SKI)) + self.assert_(new_x509_data.x509_subject_name[0].text.strip() == + "x509 subject name") + self.assert_(isinstance(new_x509_data.x509_subject_name[0], + ds.X509SubjectName)) + self.assert_(new_x509_data.x509_certificate[0].text.strip() == + "x509 certificate") + self.assert_(isinstance(new_x509_data.x509_certificate[0], + ds.X509Certificate)) + self.assert_(new_x509_data.x509_crl[0].text.strip() == "x509 crl") + self.assert_(isinstance(new_x509_data.x509_crl[0],ds.X509CRL)) + + +class TransformTest(unittest.TestCase): + + def setUp(self): + self.transform = ds.Transform() + + def testAccessors(self): + """Test for Transform accessors""" + self.transform.xpath.append(ds.XPath(text="xpath")) + self.transform.algorithm = ds.TRANSFORM_ENVELOPED + new_transform = ds.TransformFromString(self.transform.ToString()) + self.assert_(isinstance(new_transform.xpath[0], ds.XPath)) + self.assert_(new_transform.xpath[0].text.strip() == "xpath") + self.assert_(new_transform.algorithm == ds.TRANSFORM_ENVELOPED) + + def testUsingTestData(self): + """Test for TransformFromString() using test data""" + new_transform = ds.TransformFromString(ds_test_data.TEST_TRANSFORM) + self.assert_(isinstance(new_transform.xpath[0], ds.XPath)) + self.assert_(new_transform.xpath[0].text.strip() == "xpath") + self.assert_(new_transform.algorithm == ds.TRANSFORM_ENVELOPED) + + +class TransformsTest(unittest.TestCase): + + def setUp(self): + self.transforms = ds.Transforms() + + def testAccessors(self): + """Test for Transforms accessors""" + self.transforms.transform.append( + ds.TransformFromString(ds_test_data.TEST_TRANSFORM)) + self.transforms.transform.append( + ds.TransformFromString(ds_test_data.TEST_TRANSFORM)) + new_transforms = ds.TransformsFromString(self.transforms.ToString()) + self.assert_(isinstance(new_transforms.transform[0], ds.Transform)) + self.assert_(isinstance(new_transforms.transform[1], ds.Transform)) + self.assert_(new_transforms.transform[0].algorithm == + ds.TRANSFORM_ENVELOPED) + self.assert_(new_transforms.transform[1].algorithm == + ds.TRANSFORM_ENVELOPED) + self.assert_(new_transforms.transform[0].xpath[0].text.strip() == "xpath") + self.assert_(new_transforms.transform[1].xpath[0].text.strip() == "xpath") + + def testUsingTestData(self): + """Test for TransformFromString() using test data""" + new_transforms = ds.TransformsFromString(ds_test_data.TEST_TRANSFORMS) + self.assert_(isinstance(new_transforms.transform[0], ds.Transform)) + self.assert_(isinstance(new_transforms.transform[1], ds.Transform)) + self.assert_(new_transforms.transform[0].algorithm == + ds.TRANSFORM_ENVELOPED) + self.assert_(new_transforms.transform[1].algorithm == + ds.TRANSFORM_ENVELOPED) + self.assert_(new_transforms.transform[0].xpath[0].text.strip() == "xpath") + self.assert_(new_transforms.transform[1].xpath[0].text.strip() == "xpath") + + +class RetrievalMethodTest(unittest.TestCase): + + def setUp(self): + self.retrieval_method = ds.RetrievalMethod() + + def testAccessors(self): + """Test for RetrievalMethod accessors""" + self.retrieval_method.uri = "http://www.sios.com/URI" + self.retrieval_method.type = "http://www.sios.com/Type" + self.retrieval_method.transforms.append(ds.TransformsFromString( + ds_test_data.TEST_TRANSFORMS)) + new_retrieval_method = ds.RetrievalMethodFromString( + self.retrieval_method.ToString()) + self.assert_(new_retrieval_method.uri == "http://www.sios.com/URI") + self.assert_(new_retrieval_method.type == "http://www.sios.com/Type") + self.assert_(isinstance(new_retrieval_method.transforms[0], ds.Transforms)) + + def testUsingTestData(self): + """Test for RetrievalMethodFromString() using test data""" + new_retrieval_method = ds.RetrievalMethodFromString( + ds_test_data.TEST_RETRIEVAL_METHOD) + self.assert_(new_retrieval_method.uri == "http://www.sios.com/URI") + self.assert_(new_retrieval_method.type == "http://www.sios.com/Type") + self.assert_(isinstance(new_retrieval_method.transforms[0], ds.Transforms)) + + +class RSAKeyValueTest(unittest.TestCase): + + def setUp(self): + self.rsa_key_value = ds.RSAKeyValue() + + def testAccessors(self): + """Test for RSAKeyValue accessors""" + self.rsa_key_value.modulus = ds.Modulus(text="modulus") + self.rsa_key_value.exponent = ds.Exponent(text="exponent") + new_rsa_key_value = ds.RSAKeyValueFromString(self.rsa_key_value.ToString()) + self.assert_(isinstance(new_rsa_key_value.modulus, ds.Modulus)) + self.assert_(isinstance(new_rsa_key_value.exponent, ds.Exponent)) + self.assert_(new_rsa_key_value.modulus.text.strip() == "modulus") + self.assert_(new_rsa_key_value.exponent.text.strip() == "exponent") + + def testUsingTestData(self): + """Test for RSAKeyValueFromString() using test data""" + new_rsa_key_value = ds.RSAKeyValueFromString( + ds_test_data.TEST_RSA_KEY_VALUE) + self.assert_(isinstance(new_rsa_key_value.modulus, ds.Modulus)) + self.assert_(isinstance(new_rsa_key_value.exponent, ds.Exponent)) + self.assert_(new_rsa_key_value.modulus.text.strip() == "modulus") + self.assert_(new_rsa_key_value.exponent.text.strip() == "exponent") + + +class DSAKeyValueTest(unittest.TestCase): + + def setUp(self): + self.dsa_key_value = ds.DSAKeyValue() + + def testAccessors(self): + """Test for DSAKeyValue accessors""" + self.dsa_key_value.p = ds.P(text="p") + self.dsa_key_value.q = ds.Q(text="q") + self.dsa_key_value.g = ds.G(text="g") + self.dsa_key_value.y = ds.Y(text="y") + self.dsa_key_value.j = ds.J(text="j") + self.dsa_key_value.seed = ds.Seed(text="seed") + self.dsa_key_value.pgen_counter = ds.PgenCounter(text="pgen counter") + new_dsa_key_value = ds.DSAKeyValueFromString(self.dsa_key_value.ToString()) + self.assert_(isinstance(new_dsa_key_value.p, ds.P)) + self.assert_(isinstance(new_dsa_key_value.q, ds.Q)) + self.assert_(isinstance(new_dsa_key_value.g, ds.G)) + self.assert_(isinstance(new_dsa_key_value.y, ds.Y)) + self.assert_(isinstance(new_dsa_key_value.j, ds.J)) + self.assert_(isinstance(new_dsa_key_value.seed, ds.Seed)) + self.assert_(isinstance(new_dsa_key_value.pgen_counter, ds.PgenCounter)) + self.assert_(new_dsa_key_value.p.text.strip() == "p") + self.assert_(new_dsa_key_value.q.text.strip() == "q") + self.assert_(new_dsa_key_value.g.text.strip() == "g") + self.assert_(new_dsa_key_value.y.text.strip() == "y") + self.assert_(new_dsa_key_value.j.text.strip() == "j") + self.assert_(new_dsa_key_value.seed.text.strip() == "seed") + self.assert_(new_dsa_key_value.pgen_counter.text.strip() == "pgen counter") + + def testUsingTestData(self): + """Test for DSAKeyValueFromString() using test data""" + new_dsa_key_value = ds.DSAKeyValueFromString( + ds_test_data.TEST_DSA_KEY_VALUE) + self.assert_(isinstance(new_dsa_key_value.p, ds.P)) + self.assert_(isinstance(new_dsa_key_value.q, ds.Q)) + self.assert_(isinstance(new_dsa_key_value.g, ds.G)) + self.assert_(isinstance(new_dsa_key_value.y, ds.Y)) + self.assert_(isinstance(new_dsa_key_value.j, ds.J)) + self.assert_(isinstance(new_dsa_key_value.seed, ds.Seed)) + self.assert_(isinstance(new_dsa_key_value.pgen_counter, ds.PgenCounter)) + self.assert_(new_dsa_key_value.p.text.strip() == "p") + self.assert_(new_dsa_key_value.q.text.strip() == "q") + self.assert_(new_dsa_key_value.g.text.strip() == "g") + self.assert_(new_dsa_key_value.y.text.strip() == "y") + self.assert_(new_dsa_key_value.j.text.strip() == "j") + self.assert_(new_dsa_key_value.seed.text.strip() == "seed") + self.assert_(new_dsa_key_value.pgen_counter.text.strip() == "pgen counter") + + +class KeyValueTest(unittest.TestCase): + + def setUp(self): + self.key_value = ds.KeyValue() + + def testAccessors(self): + """Test for KeyValue accessors""" + self.key_value.dsa_key_value = ds.DSAKeyValueFromString( + ds_test_data.TEST_DSA_KEY_VALUE) + new_key_value = ds.KeyValueFromString(self.key_value.ToString()) + self.assert_(isinstance(new_key_value.dsa_key_value, ds.DSAKeyValue)) + self.key_value.dsa_key_value = None + self.key_value.rsa_key_value = ds.RSAKeyValueFromString( + ds_test_data.TEST_RSA_KEY_VALUE) + new_key_value = ds.KeyValueFromString(self.key_value.ToString()) + self.assert_(isinstance(new_key_value.rsa_key_value, ds.RSAKeyValue)) + + def testUsingTestData(self): + """Test for KeyValueFromString() using test data""" + new_key_value = ds.KeyValueFromString(ds_test_data.TEST_KEY_VALUE1) + self.assert_(isinstance(new_key_value.dsa_key_value, ds.DSAKeyValue)) + self.key_value.dsa_key_value = None + self.key_value.rsa_key_value = ds.RSAKeyValueFromString( + ds_test_data.TEST_RSA_KEY_VALUE) + new_key_value = ds.KeyValueFromString(ds_test_data.TEST_KEY_VALUE2) + self.assert_(isinstance(new_key_value.rsa_key_value, ds.RSAKeyValue)) + + +class KeyNameTest(unittest.TestCase): + + def setUp(self): + self.key_name = ds.KeyName() + + def testAccessors(self): + """Test for KeyName accessors""" + self.key_name.text = "key name" + new_key_name = ds.KeyNameFromString(self.key_name.ToString()) + self.assert_(new_key_name.text.strip() == "key name") + + def testUsingTestData(self): + """Test for KeyNameFromString() using test data""" + new_key_name = ds.KeyNameFromString(ds_test_data.TEST_KEY_NAME) + self.assert_(new_key_name.text.strip() == "key name") + + +class KeyInfoTest(unittest.TestCase): + def setUp(self): + self.key_info = ds.KeyInfo() + + def testAccessors(self): + """Test for KeyInfo accessors""" + self.key_info.key_name.append( + ds.KeyNameFromString(ds_test_data.TEST_KEY_NAME)) + self.key_info.key_value.append( + ds.KeyValueFromString(ds_test_data.TEST_KEY_VALUE1)) + self.key_info.retrieval_method.append( + ds.RetrievalMethodFromString(ds_test_data.TEST_RETRIEVAL_METHOD)) + self.key_info.x509_data.append( + ds.X509DataFromString(ds_test_data.TEST_X509_DATA)) + self.key_info.pgp_data.append( + ds.PGPDataFromString(ds_test_data.TEST_PGP_DATA)) + self.key_info.spki_data.append( + ds.SPKIDataFromString(ds_test_data.TEST_SPKI_DATA)) + self.key_info.mgmt_data.append( + ds.MgmtDataFromString(ds_test_data.TEST_MGMT_DATA)) + self.key_info.id = "id" + new_key_info = ds.KeyInfoFromString(self.key_info.ToString()) + + self.assert_(isinstance(new_key_info.key_name[0], ds.KeyName)) + self.assert_(isinstance(new_key_info.key_value[0], ds.KeyValue)) + self.assert_(isinstance(new_key_info.retrieval_method[0], + ds.RetrievalMethod)) + self.assert_(isinstance(new_key_info.x509_data[0], ds.X509Data)) + self.assert_(isinstance(new_key_info.pgp_data[0], ds.PGPData)) + self.assert_(isinstance(new_key_info.spki_data[0], ds.SPKIData)) + self.assert_(isinstance(new_key_info.mgmt_data[0], ds.MgmtData)) + self.assert_(new_key_info.id == "id") + + def testUsingTestData(self): + """Test for KeyInfoFromString() using test data""" + new_key_info = ds.KeyInfoFromString(ds_test_data.TEST_KEY_INFO) + self.assert_(isinstance(new_key_info.key_name[0], ds.KeyName)) + self.assert_(isinstance(new_key_info.key_value[0], ds.KeyValue)) + self.assert_(isinstance(new_key_info.retrieval_method[0], + ds.RetrievalMethod)) + self.assert_(isinstance(new_key_info.x509_data[0], ds.X509Data)) + self.assert_(isinstance(new_key_info.pgp_data[0], ds.PGPData)) + self.assert_(isinstance(new_key_info.spki_data[0], ds.SPKIData)) + self.assert_(isinstance(new_key_info.mgmt_data[0], ds.MgmtData)) + self.assert_(new_key_info.id == "id") + + +class DigestValueTest(unittest.TestCase): + + def setUp(self): + self.digest_value = ds.DigestValue() + + def testAccessors(self): + """Test for DigestValue accessors""" + self.digest_value.text = "digest value" + new_digest_value = ds.DigestValueFromString(self.digest_value.ToString()) + self.assert_(new_digest_value.text.strip() == "digest value") + + def testUsingTestData(self): + """Test for DigestValueFromString() using test data""" + new_digest_value = ds.DigestValueFromString(ds_test_data.TEST_DIGEST_VALUE) + self.assert_(new_digest_value.text.strip() == "digest value") + + +class DigestMethodTest(unittest.TestCase): + + def setUp(self): + self.digest_method = ds.DigestMethod() + + def testAccessors(self): + """Test for DigestMethod accessors""" + self.digest_method.algorithm = ds.DIGEST_SHA1 + new_digest_method = ds.DigestMethodFromString( + self.digest_method.ToString()) + self.assert_(new_digest_method.algorithm == ds.DIGEST_SHA1) + + def testUsingTestData(self): + """Test for DigestMethodFromString() using test data""" + new_digest_method = ds.DigestMethodFromString( + ds_test_data.TEST_DIGEST_METHOD) + self.assert_(new_digest_method.algorithm == ds.DIGEST_SHA1) + + +class ReferenceTest(unittest.TestCase): + + def setUp(self): + self.reference = ds.Reference() + + def testAccessors(self): + """Test for Reference accessors""" + self.reference.transforms.append(ds.TransformsFromString( + ds_test_data.TEST_TRANSFORMS)) + self.reference.digest_method.append(ds.DigestMethodFromString( + ds_test_data.TEST_DIGEST_METHOD)) + self.reference.digest_value.append(ds.DigestValueFromString( + ds_test_data.TEST_DIGEST_VALUE)) + self.reference.id = "id" + self.reference.uri = "http://www.sios.com/URI" + self.reference.type = "http://www.sios.com/Type" + new_reference = ds.ReferenceFromString(self.reference.ToString()) + self.assert_(isinstance(new_reference.transforms[0], ds.Transforms)) + self.assert_(isinstance(new_reference.digest_method[0], ds.DigestMethod)) + self.assert_(isinstance(new_reference.digest_value[0], ds.DigestValue)) + self.assert_(new_reference.id == "id") + self.assert_(new_reference.uri == "http://www.sios.com/URI") + self.assert_(new_reference.type == "http://www.sios.com/Type") + + def testUsingTestData(self): + """Test for ReferenceFromString() using test data""" + new_reference = ds.ReferenceFromString(ds_test_data.TEST_REFERENCE) + self.assert_(isinstance(new_reference.transforms[0], ds.Transforms)) + self.assert_(isinstance(new_reference.digest_method[0], ds.DigestMethod)) + self.assert_(isinstance(new_reference.digest_value[0], ds.DigestValue)) + self.assert_(new_reference.id == "id") + self.assert_(new_reference.uri == "http://www.sios.com/URI") + self.assert_(new_reference.type == "http://www.sios.com/Type") + + +class SignatureMethodTest(unittest.TestCase): + + def setUp(self): + self.signature_method = ds.SignatureMethod() + + def testAccessors(self): + """Test for SignatureMethod accessors""" + self.signature_method.algorithm = ds.SIG_RSA_SHA1 + self.signature_method.hmac_output_length = ds.HMACOutputLength(text="8") + new_signature_method = ds.SignatureMethodFromString( + self.signature_method.ToString()) + self.assert_(isinstance(new_signature_method.hmac_output_length, + ds.HMACOutputLength)) + self.assert_(new_signature_method.hmac_output_length.text.strip() == "8") + self.assert_(new_signature_method.algorithm == ds.SIG_RSA_SHA1) + + def testUsingTestData(self): + """Test for SignatureMethodFromString() using test data""" + new_signature_method = ds.SignatureMethodFromString( + ds_test_data.TEST_SIGNATURE_METHOD) + self.assert_(isinstance(new_signature_method.hmac_output_length, + ds.HMACOutputLength)) + self.assert_(new_signature_method.hmac_output_length.text.strip() == "8") + self.assert_(new_signature_method.algorithm == ds.SIG_RSA_SHA1) + + +class CanonicalizationMethodTest(unittest.TestCase): + + def setUp(self): + self.canonicalization_method = ds.CanonicalizationMethod() + + def testAccessors(self): + """Test for CanonicalizationMethod accessors""" + self.canonicalization_method.algorithm = ds.C14N_WITH_C + new_canonicalization_method = ds.CanonicalizationMethodFromString( + self.canonicalization_method.ToString()) + self.assert_(new_canonicalization_method.algorithm == ds.C14N_WITH_C) + + def testUsingTestData(self): + """Test for CanonicalizationMethodFromString() using test data""" + new_canonicalization_method = ds.CanonicalizationMethodFromString( + ds_test_data.TEST_CANONICALIZATION_METHOD) + self.assert_(new_canonicalization_method.algorithm == ds.C14N_WITH_C) + + +class SignedInfoTest(unittest.TestCase): + + def setUp(self): + self.si = ds.SignedInfo() + + def testAccessors(self): + """Test for SignedInfo accessors""" + self.si.id = "id" + self.si.canonicalization_method = ds.CanonicalizationMethodFromString( + ds_test_data.TEST_CANONICALIZATION_METHOD) + self.si.signature_method = ds.SignatureMethodFromString( + ds_test_data.TEST_SIGNATURE_METHOD) + self.si.reference.append(ds.ReferenceFromString( + ds_test_data.TEST_REFERENCE)) + new_si = ds.SignedInfoFromString(self.si.ToString()) + self.assert_(new_si.id == "id") + self.assert_(isinstance(new_si.canonicalization_method, + ds.CanonicalizationMethod)) + self.assert_(isinstance(new_si.signature_method, ds.SignatureMethod)) + self.assert_(isinstance(new_si.reference[0], ds.Reference)) + + def testUsingTestData(self): + """Test for SignedInfoFromString() using test data""" + new_si = ds.SignedInfoFromString(ds_test_data.TEST_SIGNED_INFO) + self.assert_(new_si.id == "id") + self.assert_(isinstance(new_si.canonicalization_method, + ds.CanonicalizationMethod)) + self.assert_(isinstance(new_si.signature_method, ds.SignatureMethod)) + self.assert_(isinstance(new_si.reference[0], ds.Reference)) + +class SignatureValueTest(unittest.TestCase): + + def setUp(self): + self.signature_value = ds.SignatureValue() + + def testAccessors(self): + """Test for SignatureValue accessors""" + self.signature_value.id = "id" + self.signature_value.text = "signature value" + new_signature_value = ds.SignatureValueFromString( + self.signature_value.ToString()) + self.assert_(new_signature_value.id == "id") + self.assert_(new_signature_value.text.strip() == "signature value") + + def testUsingTestData(self): + """Test for SignatureValueFromString() using test data""" + new_signature_value = ds.SignatureValueFromString( + ds_test_data.TEST_SIGNATURE_VALUE) + self.assert_(new_signature_value.id == "id") + self.assert_(new_signature_value.text.strip() == "signature value") + + +class SignatureTest(unittest.TestCase): + + def setUp(self): + self.signature = ds.Signature() + + def testAccessors(self): + """Test for Signature accessors""" + self.signature.id = "id" + self.signature.signed_info = ds.SignedInfoFromString( + ds_test_data.TEST_SIGNED_INFO) + self.signature.signature_value = ds.SignatureValueFromString( + ds_test_data.TEST_SIGNATURE_VALUE) + self.signature.key_info = ds.KeyInfoFromString(ds_test_data.TEST_KEY_INFO) + self.signature.object.append(ds.ObjectFromString(ds_test_data.TEST_OBJECT)) + + new_signature = ds.SignatureFromString(self.signature.ToString()) + self.assert_(new_signature.id == "id") + self.assert_(isinstance(new_signature.signed_info, ds.SignedInfo)) + self.assert_(isinstance(new_signature.signature_value, ds.SignatureValue)) + self.assert_(isinstance(new_signature.key_info, ds.KeyInfo)) + self.assert_(isinstance(new_signature.object[0], ds.Object)) + + def testUsingTestData(self): + """Test for SignatureValueFromString() using test data""" + new_signature = ds.SignatureFromString(ds_test_data.TEST_SIGNATURE) + self.assert_(new_signature.id == "id") + self.assert_(isinstance(new_signature.signed_info, ds.SignedInfo)) + self.assert_(isinstance(new_signature.signature_value, ds.SignatureValue)) + self.assert_(isinstance(new_signature.key_info, ds.KeyInfo)) + self.assert_(isinstance(new_signature.object[0], ds.Object)) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/md_test.py b/tests/md_test.py new file mode 100644 index 0000000..29ae249 --- /dev/null +++ b/tests/md_test.py @@ -0,0 +1,1221 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for saml2.md""" + +__author__ = 'tmatsuo@sios.com (Takashi MATSUO)' + +import unittest +try: + from xml.etree import ElementTree +except ImportError: + from elementtree import ElementTree +import saml2 +from saml2 import saml, samlp, md, md_test_data, ds_test_data +import xmldsig as ds + +class EndpointTest(unittest.TestCase): + + def setUp(self): + self.endpoint = md.Endpoint() + + def testAccessors(self): + """Test for Endpoint accessors""" + self.endpoint.binding = saml2.BINDING_HTTP_POST + self.endpoint.location = "http://www.example.com/endpoint" + self.endpoint.response_location = "http://www.example.com/response" + new_endpoint = md.EndpointFromString(self.endpoint.ToString()) + self.assert_(new_endpoint.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_endpoint.location == "http://www.example.com/endpoint") + self.assert_(new_endpoint.response_location == + "http://www.example.com/response") + + def testUsingTestData(self): + """Test for EndpointFromString() using test data.""" + new_endpoint = md.EndpointFromString(md_test_data.TEST_ENDPOINT) + self.assert_(new_endpoint.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_endpoint.location == "http://www.example.com/endpoint") + self.assert_(new_endpoint.response_location == + "http://www.example.com/response") + + +class IndexedEndpointTest(unittest.TestCase): + + def setUp(self): + self.i_e = md.IndexedEndpoint() + + def testAccessors(self): + """Test for IndexedEndpoint accessors""" + self.i_e.binding = saml2.BINDING_HTTP_POST + self.i_e.location = "http://www.example.com/endpoint" + self.i_e.response_location = "http://www.example.com/response" + self.i_e.index = "1" + self.i_e.is_default = "false" + new_i_e = md.IndexedEndpointFromString(self.i_e.ToString()) + self.assert_(new_i_e.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_i_e.location == "http://www.example.com/endpoint") + self.assert_(new_i_e.response_location == + "http://www.example.com/response") + self.assert_(new_i_e.index == "1") + self.assert_(new_i_e.is_default == "false") + + def testUsingTestData(self): + """Test for IndexedEndpointFromString() using test data.""" + new_i_e = md.IndexedEndpointFromString(md_test_data.TEST_INDEXED_ENDPOINT) + self.assert_(new_i_e.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_i_e.location == "http://www.example.com/endpoint") + self.assert_(new_i_e.response_location == + "http://www.example.com/response") + self.assert_(new_i_e.index == "1") + self.assert_(new_i_e.is_default == "false") + + +class ExtensionsTest(unittest.TestCase): + + def setUp(self): + self.extensions = md.Extensions() + + def testAccessors(self): + """Test for Extensions accessors""" + self.extensions.extension_elements.append( + saml2.ExtensionElementFromString( + """ + fuga + """)) + new_extensions = md.ExtensionsFromString(self.extensions.ToString()) + self.assert_(new_extensions.extension_elements[0].tag == "hoge") + self.assert_(new_extensions.extension_elements[0].text.strip() == + "fuga") + + +class OrganizationNameTest(unittest.TestCase): + + def setUp(self): + self.organization_name = md.OrganizationName() + + def testAccessors(self): + """Test for OrganizationName accessors""" + self.organization_name.lang = "en" + self.organization_name.text = "SIOS Technology, Inc." + new_organization_name = md.OrganizationNameFromString( + self.organization_name.ToString()) + self.assert_(new_organization_name.lang == "en") + self.assert_(new_organization_name.text.strip() == + "SIOS Technology, Inc.") + + def testUsingTestData(self): + """Test for OrganizationNameFromString() using test data.""" + new_organization_name = md.OrganizationNameFromString( + md_test_data.TEST_ORGANIZATION_NAME) + self.assert_(new_organization_name.lang == "en") + self.assert_(new_organization_name.text.strip() == + "SIOS Technology, Inc.") + + +class OrganizationDisplayNameTest(unittest.TestCase): + + def setUp(self): + self.od_name = md.OrganizationDisplayName() + + def testAccessors(self): + """Test for OrganizationDisplayName accessors""" + self.od_name.lang = "en" + self.od_name.text = "SIOS" + new_od_name = md.OrganizationDisplayNameFromString( + self.od_name.ToString()) + self.assert_(new_od_name.lang == "en") + self.assert_(new_od_name.text.strip() == "SIOS") + + def testUsingTestData(self): + """Test for OrganizationDisplayNameFromString() using test data.""" + new_od_name = md.OrganizationDisplayNameFromString( + md_test_data.TEST_ORGANIZATION_DISPLAY_NAME) + self.assert_(new_od_name.lang == "en") + self.assert_(new_od_name.text.strip() == "SIOS") + + +class OrganizationURLTest(unittest.TestCase): + + def setUp(self): + self.organization_url = md.OrganizationURL() + + def testAccessors(self): + """Test for OrganizationURL accessors""" + self.organization_url.lang = "ja" + self.organization_url.text = "http://www.sios.com/" + new_organization_url = md.OrganizationURLFromString( + self.organization_url.ToString()) + self.assert_(new_organization_url.lang == "ja") + self.assert_(new_organization_url.text.strip() == "http://www.sios.com/") + + def testUsingTestData(self): + """Test for OrganizationURLFromString() using test data.""" + new_organization_url = md.OrganizationURLFromString( + md_test_data.TEST_ORGANIZATION_URL) + self.assert_(new_organization_url.lang == "ja") + self.assert_(new_organization_url.text.strip() == "http://www.sios.com/") + + +class OrganizationTest(unittest.TestCase): + + def setUp(self): + self.organization = md.Organization() + + def testAccessors(self): + """Test for Organization accessors""" + self.organization.extensions = md.Extensions() + self.organization.organization_name.append( + md.OrganizationNameFromString(md_test_data.TEST_ORGANIZATION_NAME)) + self.organization.organization_display_name.append( + md.OrganizationDisplayNameFromString( + md_test_data.TEST_ORGANIZATION_DISPLAY_NAME)) + self.organization.organization_url.append( + md.OrganizationURLFromString(md_test_data.TEST_ORGANIZATION_URL)) + new_organization = md.OrganizationFromString(self.organization.ToString()) + self.assert_(isinstance(new_organization.extensions, md.Extensions)) + self.assert_(isinstance(new_organization.organization_name[0], + md.OrganizationName)) + self.assert_(isinstance(new_organization.organization_display_name[0], + md.OrganizationDisplayName)) + self.assert_(isinstance(new_organization.organization_url[0], + md.OrganizationURL)) + self.assert_(new_organization.organization_name[0].text.strip() == + "SIOS Technology, Inc.") + self.assert_(new_organization.organization_name[0].lang == "en") + self.assert_(new_organization.organization_display_name[0].text.strip() == + "SIOS") + self.assert_(new_organization.organization_display_name[0].lang == "en") + self.assert_(new_organization.organization_url[0].text.strip() == + "http://www.sios.com/") + self.assert_(new_organization.organization_url[0].lang == "ja") + + + def testUsingTestData(self): + """Test for OrganizationFromString() using test data.""" + new_organization = md.OrganizationFromString( + md_test_data.TEST_ORGANIZATION) + self.assert_(isinstance(new_organization.extensions, md.Extensions)) + self.assert_(isinstance(new_organization.organization_name[0], + md.OrganizationName)) + self.assert_(isinstance(new_organization.organization_display_name[0], + md.OrganizationDisplayName)) + self.assert_(isinstance(new_organization.organization_url[0], + md.OrganizationURL)) + self.assert_(new_organization.organization_name[0].text.strip() == + "SIOS Technology, Inc.") + self.assert_(new_organization.organization_name[0].lang == "en") + self.assert_(new_organization.organization_display_name[0].text.strip() == + "SIOS") + self.assert_(new_organization.organization_display_name[0].lang == "en") + self.assert_(new_organization.organization_url[0].text.strip() == + "http://www.sios.com/") + self.assert_(new_organization.organization_url[0].lang == "ja") + + +class ContactPersonTest(unittest.TestCase): + + def setUp(self): + self.contact_person = md.ContactPerson() + + def testAccessors(self): + """Test for ContactPerson accessors""" + self.contact_person.contact_type = "technical" + self.contact_person.extensions = md.Extensions() + self.contact_person.company = md.Company(text="SIOS Technology, Inc.") + self.contact_person.given_name = md.GivenName(text="Takashi") + self.contact_person.sur_name = md.SurName(text="Matsuo") + self.contact_person.email_address.append( + md.EmailAddress(text="tmatsuo@sios.com")) + self.contact_person.email_address.append( + md.EmailAddress(text="tmatsuo@shehas.net")) + self.contact_person.telephone_number.append( + md.TelephoneNumber(text="00-0000-0000")) + new_contact_person = md.ContactPersonFromString( + self.contact_person.ToString()) + self.assert_(new_contact_person.contact_type == "technical") + self.assert_(isinstance(new_contact_person.extensions, md.Extensions)) + self.assert_(new_contact_person.company.text.strip() == + "SIOS Technology, Inc.") + self.assert_(new_contact_person.given_name.text.strip() == "Takashi") + self.assert_(new_contact_person.sur_name.text.strip() == "Matsuo") + self.assert_(new_contact_person.email_address[0].text.strip() == + "tmatsuo@sios.com") + self.assert_(new_contact_person.email_address[1].text.strip() == + "tmatsuo@shehas.net") + self.assert_(new_contact_person.telephone_number[0].text.strip() == + "00-0000-0000") + + def testUsingTestData(self): + """Test for ContactPersonFromString() using test data.""" + new_contact_person = md.ContactPersonFromString( + md_test_data.TEST_CONTACT_PERSON) + self.assert_(new_contact_person.contact_type == "technical") + self.assert_(isinstance(new_contact_person.extensions, md.Extensions)) + self.assert_(new_contact_person.company.text.strip() == + "SIOS Technology, Inc.") + self.assert_(new_contact_person.given_name.text.strip() == "Takashi") + self.assert_(new_contact_person.sur_name.text.strip() == "Matsuo") + self.assert_(new_contact_person.email_address[0].text.strip() == + "tmatsuo@sios.com") + self.assert_(new_contact_person.email_address[1].text.strip() == + "tmatsuo@shehas.net") + self.assert_(new_contact_person.telephone_number[0].text.strip() == + "00-0000-0000") + +class AdditionalMetadataLocationTest(unittest.TestCase): + + def setUp(self): + self.additional_metadata_location = md.AdditionalMetadataLocation() + + def testAccessors(self): + """Test for AdditionalMetadataLocation accessors""" + self.additional_metadata_location.namespace = ( + "http://www.sios.com/namespace") + self.additional_metadata_location.text = ( + "http://www.sios.com/AdditionalMetadataLocation") + new_additional_metadata_location = md.AdditionalMetadataLocationFromString( + self.additional_metadata_location.ToString()) + self.assert_(new_additional_metadata_location.namespace == + "http://www.sios.com/namespace") + self.assert_(new_additional_metadata_location.text.strip() == + "http://www.sios.com/AdditionalMetadataLocation") + + def testUsingTestData(self): + """Test for AdditionalMetadataLocationFromString() using test data.""" + new_additional_metadata_location = md.AdditionalMetadataLocationFromString( + md_test_data.TEST_ADDITIONAL_METADATA_LOCATION) + self.assert_(new_additional_metadata_location.namespace == + "http://www.sios.com/namespace") + self.assert_(new_additional_metadata_location.text.strip() == + "http://www.sios.com/AdditionalMetadataLocation") + +class KeySizeTest(unittest.TestCase): + + def setUp(self): + self.key_size = md.KeySize() + + def testAccessors(self): + """Test for KeySize accessors""" + self.key_size.text = "128" + new_key_size = md.KeySizeFromString(self.key_size.ToString()) + self.assert_(new_key_size.text.strip() == "128") + + def testUsingTestData(self): + """Test for KeySizeFromString() using test data.""" + new_key_size = md.KeySizeFromString(md_test_data.TEST_KEY_SIZE) + self.assert_(new_key_size.text.strip() == "128") + + +class OAEPparamsTest(unittest.TestCase): + + def setUp(self): + self.oaep_params = md.OAEPparams() + + def testAccessors(self): + """Test for OAEPparams accessors""" + self.oaep_params.text = "9lWu3Q==" + new_oaep_params = md.OAEPparamsFromString(self.oaep_params.ToString()) + self.assert_(new_oaep_params.text.strip() == "9lWu3Q==") + + def testUsingTestData(self): + """Test for OAEPparamsFromString() using test data.""" + new_oaep_params = md.OAEPparamsFromString(md_test_data.TEST_OAEP_PARAMS) + self.assert_(new_oaep_params.text.strip() == "9lWu3Q==") + + +class EncryptionMethodTest(unittest.TestCase): + + def setUp(self): + self.encryption_method = md.EncryptionMethod() + + def testAccessors(self): + """Test for EncryptionMethod accessors""" + self.encryption_method.algorithm = ( + "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p") + self.encryption_method.oaep_params = md.OAEPparams(text="9lWu3Q==") + self.encryption_method.digest_method = ds.DigestMethod( + algorithm="http://www.w3.org/2000/09/xmldsig#sha1") + new_encryption_method = md.EncryptionMethodFromString( + self.encryption_method.ToString()) + self.assert_(new_encryption_method.algorithm == + "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p") + self.assert_(new_encryption_method.oaep_params.text.strip() == "9lWu3Q==") + self.assert_(new_encryption_method.digest_method.algorithm == + "http://www.w3.org/2000/09/xmldsig#sha1") + + def testUsingTestData(self): + """Test for EncryptionMethodFromString() using test data.""" + new_encryption_method = md.EncryptionMethodFromString( + md_test_data.TEST_ENCRYPTION_METHOD) + self.assert_(new_encryption_method.algorithm == + "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p") + self.assert_(new_encryption_method.oaep_params.text.strip() == "9lWu3Q==") + self.assert_(new_encryption_method.digest_method.algorithm == + "http://www.w3.org/2000/09/xmldsig#sha1") + + +class KeyDescriptorTest(unittest.TestCase): + + def setUp(self): + self.key_descriptor = md.KeyDescriptor() + + def testAccessors(self): + """Test for KeyDescriptor accessors""" + + self.key_descriptor.use = "signing" + self.key_descriptor.key_info = ds.KeyInfoFromString( + ds_test_data.TEST_KEY_INFO) + self.key_descriptor.encryption_method.append(md.EncryptionMethodFromString( + md_test_data.TEST_ENCRYPTION_METHOD)) + new_key_descriptor = md.KeyDescriptorFromString( + self.key_descriptor.ToString()) + self.assert_(new_key_descriptor.use == "signing") + self.assert_(isinstance(new_key_descriptor.key_info, ds.KeyInfo)) + self.assert_(isinstance(new_key_descriptor.encryption_method[0], + md.EncryptionMethod)) + + def testUsingTestData(self): + """Test for KeyDescriptorFromString() using test data.""" + new_key_descriptor = md.KeyDescriptorFromString( + md_test_data.TEST_KEY_DESCRIPTOR) + self.assert_(new_key_descriptor.use == "signing") + self.assert_(isinstance(new_key_descriptor.key_info, ds.KeyInfo)) + self.assert_(isinstance(new_key_descriptor.encryption_method[0], + md.EncryptionMethod)) + + +class RoleDescriptorTest(unittest.TestCase): + def setUp(self): + self.role_descriptor = md.RoleDescriptor() + + def testAccessors(self): + """Test for RoleDescriptor accessors""" + self.role_descriptor.id = "ID" + self.role_descriptor.valid_until = "2008-09-14T01:05:02Z" + self.role_descriptor.cache_duration = "10:00:00:00" + self.role_descriptor.protocol_support_enumeration = samlp.SAMLP_NAMESPACE + self.role_descriptor.error_url = "http://www.sios.com/errorURL" + self.role_descriptor.signature = ds.GetEmptySignature() + self.role_descriptor.extensions = md.Extensions() + self.role_descriptor.key_descriptor.append(md.KeyDescriptorFromString( + md_test_data.TEST_KEY_DESCRIPTOR)) + self.role_descriptor.organization = md.Organization() + self.role_descriptor.contact_person.append(md.ContactPerson()) + + new_role_descriptor = md.RoleDescriptorFromString( + self.role_descriptor.ToString()) + self.assert_(new_role_descriptor.id == "ID") + self.assert_(new_role_descriptor.valid_until == "2008-09-14T01:05:02Z") + self.assert_(new_role_descriptor.cache_duration == "10:00:00:00") + self.assert_(new_role_descriptor.protocol_support_enumeration == + samlp.SAMLP_NAMESPACE) + self.assert_(new_role_descriptor.error_url == + "http://www.sios.com/errorURL") + self.assert_(isinstance(new_role_descriptor.signature, ds.Signature)) + self.assert_(isinstance(new_role_descriptor.extensions, md.Extensions)) + self.assert_(isinstance(new_role_descriptor.key_descriptor[0], + md.KeyDescriptor)) + self.assert_(isinstance(new_role_descriptor.organization, md.Organization)) + self.assert_(isinstance(new_role_descriptor.contact_person[0], + md.ContactPerson)) + + def testUsingTestData(self): + """Test for RoleDescriptorFromString() using test data.""" + new_role_descriptor = md.RoleDescriptorFromString( + md_test_data.TEST_ROLE_DESCRIPTOR) + self.assert_(new_role_descriptor.id == "ID") + self.assert_(new_role_descriptor.valid_until == "2008-09-14T01:05:02Z") + self.assert_(new_role_descriptor.cache_duration == "10:00:00:00") + self.assert_(new_role_descriptor.protocol_support_enumeration == + samlp.SAMLP_NAMESPACE) + self.assert_(new_role_descriptor.error_url == + "http://www.sios.com/errorURL") + self.assert_(isinstance(new_role_descriptor.signature, ds.Signature)) + self.assert_(isinstance(new_role_descriptor.extensions, md.Extensions)) + self.assert_(isinstance(new_role_descriptor.key_descriptor[0], + md.KeyDescriptor)) + self.assert_(isinstance(new_role_descriptor.organization, md.Organization)) + self.assert_(isinstance(new_role_descriptor.contact_person[0], + md.ContactPerson)) + +class SSODescriptorTest(unittest.TestCase): + def setUp(self): + self.sso_descriptor = md.SSODescriptor() + + def testAccessors(self): + """Test for SSODescriptor accessors""" + self.sso_descriptor.id = "ID" + self.sso_descriptor.valid_until = "2008-09-14T01:05:02Z" + self.sso_descriptor.cache_duration = "10:00:00:00" + self.sso_descriptor.protocol_support_enumeration = samlp.SAMLP_NAMESPACE + self.sso_descriptor.error_url = "http://www.sios.com/errorURL" + self.sso_descriptor.signature = ds.GetEmptySignature() + self.sso_descriptor.extensions = md.Extensions() + self.sso_descriptor.key_descriptor.append(md.KeyDescriptorFromString( + md_test_data.TEST_KEY_DESCRIPTOR)) + self.sso_descriptor.organization = md.Organization() + self.sso_descriptor.contact_person.append(md.ContactPerson()) + self.sso_descriptor.artifact_resolution_service.append( + md.ArtifactResolutionService()) + self.sso_descriptor.single_logout_service.append( + md.SingleLogoutService()) + self.sso_descriptor.manage_name_id_service.append( + md.ManageNameIDService()) + self.sso_descriptor.name_id_format.append( + md.NameIDFormat()) + + new_sso_descriptor = md.SSODescriptorFromString( + self.sso_descriptor.ToString()) + self.assert_(new_sso_descriptor.id == "ID") + self.assert_(new_sso_descriptor.valid_until == "2008-09-14T01:05:02Z") + self.assert_(new_sso_descriptor.cache_duration == "10:00:00:00") + self.assert_(new_sso_descriptor.protocol_support_enumeration == + samlp.SAMLP_NAMESPACE) + self.assert_(new_sso_descriptor.error_url == + "http://www.sios.com/errorURL") + self.assert_(isinstance(new_sso_descriptor.signature, ds.Signature)) + self.assert_(isinstance(new_sso_descriptor.extensions, md.Extensions)) + self.assert_(isinstance(new_sso_descriptor.key_descriptor[0], + md.KeyDescriptor)) + self.assert_(isinstance(new_sso_descriptor.organization, md.Organization)) + self.assert_(isinstance(new_sso_descriptor.contact_person[0], + md.ContactPerson)) + self.assert_(isinstance(new_sso_descriptor.artifact_resolution_service[0], + md.ArtifactResolutionService)) + self.assert_(isinstance(new_sso_descriptor.single_logout_service[0], + md.SingleLogoutService)) + self.assert_(isinstance(new_sso_descriptor.manage_name_id_service[0], + md.ManageNameIDService)) + self.assert_(isinstance(new_sso_descriptor.name_id_format[0], + md.NameIDFormat)) + + def testUsingTestData(self): + """Test for SSODescriptorFromString() using test data.""" + new_sso_descriptor = md.SSODescriptorFromString( + md_test_data.TEST_SSO_DESCRIPTOR) + self.assert_(new_sso_descriptor.id == "ID") + self.assert_(new_sso_descriptor.valid_until == "2008-09-14T01:05:02Z") + self.assert_(new_sso_descriptor.cache_duration == "10:00:00:00") + self.assert_(new_sso_descriptor.protocol_support_enumeration == + samlp.SAMLP_NAMESPACE) + self.assert_(new_sso_descriptor.error_url == + "http://www.sios.com/errorURL") + self.assert_(isinstance(new_sso_descriptor.signature, ds.Signature)) + self.assert_(isinstance(new_sso_descriptor.extensions, md.Extensions)) + self.assert_(isinstance(new_sso_descriptor.key_descriptor[0], + md.KeyDescriptor)) + self.assert_(isinstance(new_sso_descriptor.organization, md.Organization)) + self.assert_(isinstance(new_sso_descriptor.contact_person[0], + md.ContactPerson)) + self.assert_(isinstance(new_sso_descriptor.artifact_resolution_service[0], + md.ArtifactResolutionService)) + self.assert_(isinstance(new_sso_descriptor.single_logout_service[0], + md.SingleLogoutService)) + self.assert_(isinstance(new_sso_descriptor.manage_name_id_service[0], + md.ManageNameIDService)) + self.assert_(isinstance(new_sso_descriptor.name_id_format[0], + md.NameIDFormat)) + + +class ArtifactResolutionServiceTest(unittest.TestCase): + + def setUp(self): + self.i_e = md.ArtifactResolutionService() + + def testAccessors(self): + """Test for ArtifactResolutionService accessors""" + self.i_e.binding = saml2.BINDING_HTTP_POST + self.i_e.location = "http://www.example.com/endpoint" + self.i_e.response_location = "http://www.example.com/response" + self.i_e.index = "1" + self.i_e.is_default = "false" + new_i_e = md.ArtifactResolutionServiceFromString(self.i_e.ToString()) + self.assert_(new_i_e.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_i_e.location == "http://www.example.com/endpoint") + self.assert_(new_i_e.response_location == + "http://www.example.com/response") + self.assert_(new_i_e.index == "1") + self.assert_(new_i_e.is_default == "false") + + def testUsingTestData(self): + """Test for ArtifactResolutionServiceFromString() using test data.""" + new_i_e = md.ArtifactResolutionServiceFromString( + md_test_data.TEST_ARTIFACT_RESOLUTION_SERVICE) + self.assert_(new_i_e.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_i_e.location == "http://www.example.com/endpoint") + self.assert_(new_i_e.response_location == + "http://www.example.com/response") + self.assert_(new_i_e.index == "1") + self.assert_(new_i_e.is_default == "false") + + +class SingleLogoutService(unittest.TestCase): + + def setUp(self): + self.endpoint = md.SingleLogoutService() + + def testAccessors(self): + """Test for SingleLogoutService accessors""" + self.endpoint.binding = saml2.BINDING_HTTP_POST + self.endpoint.location = "http://www.example.com/endpoint" + self.endpoint.response_location = "http://www.example.com/response" + new_endpoint = md.SingleLogoutServiceFromString(self.endpoint.ToString()) + self.assert_(new_endpoint.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_endpoint.location == "http://www.example.com/endpoint") + self.assert_(new_endpoint.response_location == + "http://www.example.com/response") + + def testUsingTestData(self): + """Test for SingleLogoutServiceFromString() using test data.""" + new_endpoint = md.SingleLogoutServiceFromString( + md_test_data.TEST_SINGLE_LOGOUT_SERVICE) + self.assert_(new_endpoint.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_endpoint.location == "http://www.example.com/endpoint") + self.assert_(new_endpoint.response_location == + "http://www.example.com/response") + + +class ManageNameIDServiceTest(unittest.TestCase): + + def setUp(self): + self.endpoint = md.ManageNameIDService() + + def testAccessors(self): + """Test for ManageNameIDService accessors""" + self.endpoint.binding = saml2.BINDING_HTTP_POST + self.endpoint.location = "http://www.example.com/endpoint" + self.endpoint.response_location = "http://www.example.com/response" + new_endpoint = md.ManageNameIDServiceFromString(self.endpoint.ToString()) + self.assert_(new_endpoint.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_endpoint.location == "http://www.example.com/endpoint") + self.assert_(new_endpoint.response_location == + "http://www.example.com/response") + + def testUsingTestData(self): + """Test for ManageNameIDServiceFromString() using test data.""" + new_endpoint = md.ManageNameIDServiceFromString( + md_test_data.TEST_MANAGE_NAMEID_SERVICE) + self.assert_(new_endpoint.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_endpoint.location == "http://www.example.com/endpoint") + self.assert_(new_endpoint.response_location == + "http://www.example.com/response") + + +class NameIDFormatTest(unittest.TestCase): + + def setUp(self): + self.name_id_format = md.NameIDFormat() + + def testAccessors(self): + """Test for NameIDFormat accessors""" + self.name_id_format.text = saml.NAMEID_FORMAT_EMAILADDRESS + new_name_id_format = md.NameIDFormatFromString( + self.name_id_format.ToString()) + self.assert_(new_name_id_format.text.strip() == + saml.NAMEID_FORMAT_EMAILADDRESS) + + def testUsingTestData(self): + """Test for NameIDFormatFromString() using test data.""" + new_name_id_format = md.NameIDFormatFromString( + md_test_data.TEST_NAME_ID_FORMAT) + self.assert_(new_name_id_format.text.strip() == + saml.NAMEID_FORMAT_EMAILADDRESS) + + +class SingleSignOnServiceTest(unittest.TestCase): + + def setUp(self): + self.endpoint = md.SingleSignOnService() + + def testAccessors(self): + """Test for SingelSignOnService accessors""" + self.endpoint.binding = saml2.BINDING_HTTP_POST + self.endpoint.location = "http://www.example.com/endpoint" + self.endpoint.response_location = "http://www.example.com/response" + new_endpoint = md.SingleSignOnServiceFromString(self.endpoint.ToString()) + self.assert_(new_endpoint.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_endpoint.location == "http://www.example.com/endpoint") + self.assert_(new_endpoint.response_location == + "http://www.example.com/response") + + def testUsingTestData(self): + """Test for SingelSignOnServiceFromString() using test data.""" + new_endpoint = md.SingleSignOnServiceFromString( + md_test_data.TEST_SINGLE_SIGN_ON_SERVICE) + self.assert_(new_endpoint.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_endpoint.location == "http://www.example.com/endpoint") + self.assert_(new_endpoint.response_location == + "http://www.example.com/response") + +class NameIDMappingServiceTest(unittest.TestCase): + + def setUp(self): + self.endpoint = md.NameIDMappingService() + + def testAccessors(self): + """Test for NameIDMappingService accessors""" + self.endpoint.binding = saml2.BINDING_HTTP_POST + self.endpoint.location = "http://www.example.com/endpoint" + self.endpoint.response_location = "http://www.example.com/response" + new_endpoint = md.NameIDMappingServiceFromString(self.endpoint.ToString()) + self.assert_(new_endpoint.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_endpoint.location == "http://www.example.com/endpoint") + self.assert_(new_endpoint.response_location == + "http://www.example.com/response") + + def testUsingTestData(self): + """Test for NameIDMappingServiceFromString() using test data.""" + new_endpoint = md.NameIDMappingServiceFromString( + md_test_data.TEST_NAME_ID_MAPPING_SERVICE) + self.assert_(new_endpoint.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_endpoint.location == "http://www.example.com/endpoint") + self.assert_(new_endpoint.response_location == + "http://www.example.com/response") + +class AssertionIDRequestServiceTest(unittest.TestCase): + + def setUp(self): + self.endpoint = md.AssertionIDRequestService() + + def testAccessors(self): + """Test for AssertionIDRequestService accessors""" + self.endpoint.binding = saml2.BINDING_HTTP_POST + self.endpoint.location = "http://www.example.com/endpoint" + self.endpoint.response_location = "http://www.example.com/response" + new_endpoint = md.AssertionIDRequestServiceFromString( + self.endpoint.ToString()) + self.assert_(new_endpoint.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_endpoint.location == "http://www.example.com/endpoint") + self.assert_(new_endpoint.response_location == + "http://www.example.com/response") + + def testUsingTestData(self): + """Test for AssertionIDRequestServiceFromString() using test data.""" + new_endpoint = md.AssertionIDRequestServiceFromString( + md_test_data.TEST_ASSERTION_ID_REQUEST_SERVICE) + self.assert_(new_endpoint.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_endpoint.location == "http://www.example.com/endpoint") + self.assert_(new_endpoint.response_location == + "http://www.example.com/response") + +class AttributeProfileTest(unittest.TestCase): + + def setUp(self): + self.attribute_profile = md.AttributeProfile() + + def testAccessors(self): + """Test for AttributeProfile accessors""" + self.attribute_profile.text = saml.PROFILE_ATTRIBUTE_BASIC + new_attribute_profile = md.AttributeProfileFromString( + self.attribute_profile.ToString()) + self.assert_(new_attribute_profile.text.strip() == + saml.PROFILE_ATTRIBUTE_BASIC) + + def testUsingTestData(self): + """Test for NameIDFormatFromString() using test data.""" + new_attribute_profile = md.AttributeProfileFromString( + md_test_data.TEST_ATTRIBUTE_PROFILE) + self.assert_(new_attribute_profile.text.strip() == + saml.PROFILE_ATTRIBUTE_BASIC) + + +class IDPSSODescriptorTest(unittest.TestCase): + def setUp(self): + self.idp_sso_descriptor = md.IDPSSODescriptor() + + def testAccessors(self): + """Test for IDPSSODescriptor accessors""" + self.idp_sso_descriptor.id = "ID" + self.idp_sso_descriptor.valid_until = "2008-09-14T01:05:02Z" + self.idp_sso_descriptor.cache_duration = "10:00:00:00" + self.idp_sso_descriptor.protocol_support_enumeration = \ + samlp.SAMLP_NAMESPACE + self.idp_sso_descriptor.error_url = "http://www.sios.com/errorURL" + self.idp_sso_descriptor.signature = ds.GetEmptySignature() + self.idp_sso_descriptor.extensions = md.Extensions() + self.idp_sso_descriptor.key_descriptor.append(md.KeyDescriptorFromString( + md_test_data.TEST_KEY_DESCRIPTOR)) + self.idp_sso_descriptor.organization = md.Organization() + self.idp_sso_descriptor.contact_person.append(md.ContactPerson()) + self.idp_sso_descriptor.artifact_resolution_service.append( + md.ArtifactResolutionService()) + self.idp_sso_descriptor.single_logout_service.append( + md.SingleLogoutService()) + self.idp_sso_descriptor.manage_name_id_service.append( + md.ManageNameIDService()) + self.idp_sso_descriptor.name_id_format.append( + md.NameIDFormat()) + self.idp_sso_descriptor.want_authn_requests_signed = 'true' + self.idp_sso_descriptor.single_sign_on_service.append( + md.SingleSignOnService()) + self.idp_sso_descriptor.name_id_mapping_service.append( + md.NameIDMappingService()) + self.idp_sso_descriptor.assertion_id_request_service.append( + md.AssertionIDRequestService()) + self.idp_sso_descriptor.attribute_profile.append( + md.AttributeProfile()) + self.idp_sso_descriptor.attribute.append(saml.Attribute()) + + new_idp_sso_descriptor = md.IDPSSODescriptorFromString( + self.idp_sso_descriptor.ToString()) + self.assert_(new_idp_sso_descriptor.id == "ID") + self.assert_(new_idp_sso_descriptor.valid_until == "2008-09-14T01:05:02Z") + self.assert_(new_idp_sso_descriptor.cache_duration == "10:00:00:00") + self.assert_(new_idp_sso_descriptor.protocol_support_enumeration == + samlp.SAMLP_NAMESPACE) + self.assert_(new_idp_sso_descriptor.error_url == + "http://www.sios.com/errorURL") + self.assert_(isinstance(new_idp_sso_descriptor.signature, ds.Signature)) + self.assert_(isinstance(new_idp_sso_descriptor.extensions, md.Extensions)) + self.assert_(isinstance(new_idp_sso_descriptor.key_descriptor[0], + md.KeyDescriptor)) + self.assert_(isinstance(new_idp_sso_descriptor.organization, + md.Organization)) + self.assert_(isinstance(new_idp_sso_descriptor.contact_person[0], + md.ContactPerson)) + self.assert_(isinstance( + new_idp_sso_descriptor.artifact_resolution_service[0], + md.ArtifactResolutionService)) + self.assert_(isinstance(new_idp_sso_descriptor.single_logout_service[0], + md.SingleLogoutService)) + self.assert_(isinstance(new_idp_sso_descriptor.manage_name_id_service[0], + md.ManageNameIDService)) + self.assert_(isinstance(new_idp_sso_descriptor.name_id_format[0], + md.NameIDFormat)) + self.assert_(new_idp_sso_descriptor.want_authn_requests_signed == "true") + self.assert_(isinstance(new_idp_sso_descriptor.single_sign_on_service[0], + md.SingleSignOnService)) + self.assert_(isinstance(new_idp_sso_descriptor.name_id_mapping_service[0], + md.NameIDMappingService)) + self.assert_(isinstance( + new_idp_sso_descriptor.assertion_id_request_service[0], + md.AssertionIDRequestService)) + self.assert_(isinstance(new_idp_sso_descriptor.attribute_profile[0], + md.AttributeProfile)) + self.assert_(isinstance(new_idp_sso_descriptor.attribute[0], + saml.Attribute)) + + def testUsingTestData(self): + """Test for IDPSSODescriptorFromString() using test data.""" + new_idp_sso_descriptor = md.IDPSSODescriptorFromString( + md_test_data.TEST_IDP_SSO_DESCRIPTOR) + self.assert_(new_idp_sso_descriptor.id == "ID") + self.assert_(new_idp_sso_descriptor.valid_until == "2008-09-14T01:05:02Z") + self.assert_(new_idp_sso_descriptor.cache_duration == "10:00:00:00") + self.assert_(new_idp_sso_descriptor.protocol_support_enumeration == + samlp.SAMLP_NAMESPACE) + self.assert_(new_idp_sso_descriptor.error_url == + "http://www.sios.com/errorURL") + self.assert_(isinstance(new_idp_sso_descriptor.signature, ds.Signature)) + self.assert_(isinstance(new_idp_sso_descriptor.extensions, md.Extensions)) + self.assert_(isinstance(new_idp_sso_descriptor.key_descriptor[0], + md.KeyDescriptor)) + self.assert_(isinstance(new_idp_sso_descriptor.organization, + md.Organization)) + self.assert_(isinstance(new_idp_sso_descriptor.contact_person[0], + md.ContactPerson)) + self.assert_(isinstance( + new_idp_sso_descriptor.artifact_resolution_service[0], + md.ArtifactResolutionService)) + self.assert_(isinstance(new_idp_sso_descriptor.single_logout_service[0], + md.SingleLogoutService)) + self.assert_(isinstance(new_idp_sso_descriptor.manage_name_id_service[0], + md.ManageNameIDService)) + self.assert_(isinstance(new_idp_sso_descriptor.name_id_format[0], + md.NameIDFormat)) + self.assert_(new_idp_sso_descriptor.want_authn_requests_signed == "true") + self.assert_(isinstance(new_idp_sso_descriptor.single_sign_on_service[0], + md.SingleSignOnService)) + self.assert_(isinstance(new_idp_sso_descriptor.name_id_mapping_service[0], + md.NameIDMappingService)) + self.assert_(isinstance( + new_idp_sso_descriptor.assertion_id_request_service[0], + md.AssertionIDRequestService)) + self.assert_(isinstance(new_idp_sso_descriptor.attribute_profile[0], + md.AttributeProfile)) + self.assert_(isinstance(new_idp_sso_descriptor.attribute[0], + saml.Attribute)) + + +class AssertionConsumerServiceTest(unittest.TestCase): + + def setUp(self): + self.i_e = md.AssertionConsumerService() + + def testAccessors(self): + """Test for AssertionConsumerService accessors""" + self.i_e.binding = saml2.BINDING_HTTP_POST + self.i_e.location = "http://www.example.com/endpoint" + self.i_e.response_location = "http://www.example.com/response" + self.i_e.index = "1" + self.i_e.is_default = "false" + new_i_e = md.AssertionConsumerServiceFromString(self.i_e.ToString()) + self.assert_(new_i_e.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_i_e.location == "http://www.example.com/endpoint") + self.assert_(new_i_e.response_location == + "http://www.example.com/response") + self.assert_(new_i_e.index == "1") + self.assert_(new_i_e.is_default == "false") + + def testUsingTestData(self): + """Test for AssertionConsumerServiceFromString() using test data.""" + new_i_e = md.AssertionConsumerServiceFromString( + md_test_data.TEST_ASSERTION_CONSUMER_SERVICE) + self.assert_(new_i_e.binding == saml2.BINDING_HTTP_POST) + self.assert_(new_i_e.location == "http://www.example.com/endpoint") + self.assert_(new_i_e.response_location == + "http://www.example.com/response") + self.assert_(new_i_e.index == "1") + self.assert_(new_i_e.is_default == "false") + + +class RequestedAttributeTest(unittest.TestCase): + + def setUp(self): + self.requested_attribute = md.RequestedAttribute() + + def testAccessors(self): + """Test for RequestedAttribute accessors""" + self.assert_(isinstance(self.requested_attribute, saml.Attribute)) + self.assert_(isinstance(self.requested_attribute, md.RequestedAttribute)) + self.assert_(self.requested_attribute.is_required is None) + self.requested_attribute.is_required = "true" + new_requested_attribute = md.RequestedAttributeFromString( + self.requested_attribute.ToString()) + self.assert_(new_requested_attribute.is_required == "true") + self.assert_(isinstance(new_requested_attribute, saml.Attribute)) + self.assert_(isinstance(new_requested_attribute, md.RequestedAttribute)) + + def testUsingTestData(self): + """Test for RequestedAttributeFromString() using test data.""" + new_requested_attribute = md.RequestedAttributeFromString( + md_test_data.TEST_REQUESTED_ATTRIBUTE) + self.assert_(new_requested_attribute.is_required == "true") + self.assert_(isinstance(new_requested_attribute, saml.Attribute)) + self.assert_(isinstance(new_requested_attribute, md.RequestedAttribute)) + + +class ServiceNameTest(unittest.TestCase): + + def setUp(self): + self.service_name = md.ServiceName() + + def testAccessors(self): + """Test for ServiceName accessors""" + self.service_name.lang = "en" + self.service_name.text = "SIOS mail" + new_service_name = md.ServiceNameFromString(self.service_name.ToString()) + self.assert_(new_service_name.lang == "en") + self.assert_(new_service_name.text.strip() == "SIOS mail") + + def testUsingTestData(self): + """Test for OrganizationNameFromString() using test data.""" + new_service_name = md.ServiceNameFromString(md_test_data.TEST_SERVICE_NAME) + self.assert_(new_service_name.lang == "en") + self.assert_(new_service_name.text.strip() == "SIOS mail") + + +class ServiceDescriptionTest(unittest.TestCase): + + def setUp(self): + self.service_description = md.ServiceDescription() + + def testAccessors(self): + """Test for ServiceDescription accessors""" + self.service_description.lang = "en" + self.service_description.text = "SIOS mail service" + new_service_description = md.ServiceDescriptionFromString( + self.service_description.ToString()) + self.assert_(new_service_description.lang == "en") + self.assert_(new_service_description.text.strip() == + "SIOS mail service") + + def testUsingTestData(self): + """Test for OrganizationNameFromString() using test data.""" + new_service_description = md.ServiceDescriptionFromString( + md_test_data.TEST_SERVICE_DESCRIPTION) + self.assert_(new_service_description.lang == "en") + self.assert_(new_service_description.text.strip() == + "SIOS mail service") + + +class AttributeConsumingServiceTest(unittest.TestCase): + + def setUp(self): + self.attribute_consuming_service = md.AttributeConsumingService() + + def testAccessors(self): + """Test for AttributeConsumingService accessors""" + self.attribute_consuming_service.service_name.append(md.ServiceName()) + self.attribute_consuming_service.service_description.append( + md.ServiceDescription()) + self.attribute_consuming_service.requested_attribute.append( + md.RequestedAttribute()) + self.attribute_consuming_service.index = "1" + self.attribute_consuming_service.is_default = "true" + + new_attribute_consuming_service = md.AttributeConsumingServiceFromString( + self.attribute_consuming_service.ToString()) + self.assert_(new_attribute_consuming_service.index == "1") + self.assert_(new_attribute_consuming_service.is_default == "true") + self.assert_(isinstance(new_attribute_consuming_service.service_name[0], + md.ServiceName)) + self.assert_(isinstance( + new_attribute_consuming_service.service_description[0], + md.ServiceDescription)) + self.assert_(isinstance( + new_attribute_consuming_service.requested_attribute[0], + md.RequestedAttribute)) + + def testUsingTestData(self): + """Test for AttributeConsumingServiceFromString() using test data.""" + new_attribute_consuming_service = md.AttributeConsumingServiceFromString( + md_test_data.TEST_ATTRIBUTE_CONSUMING_SERVICE) + self.assert_(new_attribute_consuming_service.index == "1") + self.assert_(new_attribute_consuming_service.is_default == "true") + self.assert_(isinstance(new_attribute_consuming_service.service_name[0], + md.ServiceName)) + self.assert_(isinstance( + new_attribute_consuming_service.service_description[0], + md.ServiceDescription)) + self.assert_(isinstance( + new_attribute_consuming_service.requested_attribute[0], + md.RequestedAttribute)) + + +class SPSSODescriptorTest(unittest.TestCase): + def setUp(self): + self.sp_sso_descriptor = md.SPSSODescriptor() + + def testAccessors(self): + """Test for SPSSODescriptor accessors""" + self.sp_sso_descriptor.id = "ID" + self.sp_sso_descriptor.valid_until = "2008-09-14T01:05:02Z" + self.sp_sso_descriptor.cache_duration = "10:00:00:00" + self.sp_sso_descriptor.protocol_support_enumeration = \ + samlp.SAMLP_NAMESPACE + self.sp_sso_descriptor.error_url = "http://www.sios.com/errorURL" + self.sp_sso_descriptor.signature = ds.GetEmptySignature() + self.sp_sso_descriptor.extensions = md.Extensions() + self.sp_sso_descriptor.key_descriptor.append(md.KeyDescriptorFromString( + md_test_data.TEST_KEY_DESCRIPTOR)) + self.sp_sso_descriptor.organization = md.Organization() + self.sp_sso_descriptor.contact_person.append(md.ContactPerson()) + self.sp_sso_descriptor.artifact_resolution_service.append( + md.ArtifactResolutionService()) + self.sp_sso_descriptor.single_logout_service.append( + md.SingleLogoutService()) + self.sp_sso_descriptor.manage_name_id_service.append( + md.ManageNameIDService()) + self.sp_sso_descriptor.name_id_format.append( + md.NameIDFormat()) + self.sp_sso_descriptor.authn_requests_signed = "true" + self.sp_sso_descriptor.want_assertions_signed = "true" + self.sp_sso_descriptor.assertion_consumer_service.append( + md.AssertionConsumerService()) + self.sp_sso_descriptor.attribute_consuming_service.append( + md.AttributeConsumingService()) + + new_sp_sso_descriptor = md.SPSSODescriptorFromString( + self.sp_sso_descriptor.ToString()) + self.assert_(new_sp_sso_descriptor.id == "ID") + self.assert_(new_sp_sso_descriptor.valid_until == "2008-09-14T01:05:02Z") + self.assert_(new_sp_sso_descriptor.cache_duration == "10:00:00:00") + self.assert_(new_sp_sso_descriptor.protocol_support_enumeration == + samlp.SAMLP_NAMESPACE) + self.assert_(new_sp_sso_descriptor.error_url == + "http://www.sios.com/errorURL") + self.assert_(isinstance(new_sp_sso_descriptor.signature, ds.Signature)) + self.assert_(isinstance(new_sp_sso_descriptor.extensions, md.Extensions)) + self.assert_(isinstance(new_sp_sso_descriptor.key_descriptor[0], + md.KeyDescriptor)) + self.assert_(isinstance(new_sp_sso_descriptor.organization, + md.Organization)) + self.assert_(isinstance(new_sp_sso_descriptor.contact_person[0], + md.ContactPerson)) + self.assert_(isinstance( + new_sp_sso_descriptor.artifact_resolution_service[0], + md.ArtifactResolutionService)) + self.assert_(isinstance(new_sp_sso_descriptor.single_logout_service[0], + md.SingleLogoutService)) + self.assert_(isinstance(new_sp_sso_descriptor.manage_name_id_service[0], + md.ManageNameIDService)) + self.assert_(isinstance(new_sp_sso_descriptor.name_id_format[0], + md.NameIDFormat)) + self.assert_(new_sp_sso_descriptor.authn_requests_signed == "true") + self.assert_(new_sp_sso_descriptor.want_assertions_signed == "true") + self.assert_(isinstance( + new_sp_sso_descriptor.assertion_consumer_service[0], + md.AssertionConsumerService)) + self.assert_(isinstance( + new_sp_sso_descriptor.attribute_consuming_service[0], + md.AttributeConsumingService)) + + def testUsingTestData(self): + """Test for SPSSODescriptorFromString() using test data.""" + new_sp_sso_descriptor = md.SPSSODescriptorFromString( + md_test_data.TEST_SP_SSO_DESCRIPTOR) + self.assert_(new_sp_sso_descriptor.id == "ID") + self.assert_(new_sp_sso_descriptor.valid_until == "2008-09-14T01:05:02Z") + self.assert_(new_sp_sso_descriptor.cache_duration == "10:00:00:00") + self.assert_(new_sp_sso_descriptor.protocol_support_enumeration == + samlp.SAMLP_NAMESPACE) + self.assert_(new_sp_sso_descriptor.error_url == + "http://www.sios.com/errorURL") + self.assert_(isinstance(new_sp_sso_descriptor.signature, ds.Signature)) + self.assert_(isinstance(new_sp_sso_descriptor.extensions, md.Extensions)) + self.assert_(isinstance(new_sp_sso_descriptor.key_descriptor[0], + md.KeyDescriptor)) + self.assert_(isinstance(new_sp_sso_descriptor.organization, + md.Organization)) + self.assert_(isinstance(new_sp_sso_descriptor.contact_person[0], + md.ContactPerson)) + self.assert_(isinstance( + new_sp_sso_descriptor.artifact_resolution_service[0], + md.ArtifactResolutionService)) + self.assert_(isinstance(new_sp_sso_descriptor.single_logout_service[0], + md.SingleLogoutService)) + self.assert_(isinstance(new_sp_sso_descriptor.manage_name_id_service[0], + md.ManageNameIDService)) + self.assert_(isinstance(new_sp_sso_descriptor.name_id_format[0], + md.NameIDFormat)) + self.assert_(new_sp_sso_descriptor.authn_requests_signed == "true") + self.assert_(new_sp_sso_descriptor.want_assertions_signed == "true") + self.assert_(isinstance( + new_sp_sso_descriptor.assertion_consumer_service[0], + md.AssertionConsumerService)) + self.assert_(isinstance( + new_sp_sso_descriptor.attribute_consuming_service[0], + md.AttributeConsumingService)) + + +class EntityDescriptorTest(unittest.TestCase): + def setUp(self): + self.entity_descriptor = md.EntityDescriptor() + + def testAccessors(self): + """Test for RoleDescriptor accessors""" + self.entity_descriptor.id = "ID" + self.entity_descriptor.entity_id = "entityID" + self.entity_descriptor.valid_until = "2008-09-14T01:05:02Z" + self.entity_descriptor.cache_duration = "10:00:00:00" + + self.entity_descriptor.signature = ds.GetEmptySignature() + self.entity_descriptor.extensions = md.Extensions() + self.entity_descriptor.role_descriptor.append(md.RoleDescriptor()) + self.entity_descriptor.idp_sso_descriptor.append(md.IDPSSODescriptor()) + self.entity_descriptor.sp_sso_descriptor.append(md.SPSSODescriptor()) + self.entity_descriptor.organization = md.Organization() + self.entity_descriptor.contact_person.append(md.ContactPerson()) + self.entity_descriptor.additional_metadata_location.append( + md.AdditionalMetadataLocation()) + + new_entity_descriptor = md.EntityDescriptorFromString( + self.entity_descriptor.ToString()) + self.assert_(new_entity_descriptor.id == "ID") + self.assert_(new_entity_descriptor.entity_id == "entityID") + self.assert_(new_entity_descriptor.valid_until == "2008-09-14T01:05:02Z") + self.assert_(new_entity_descriptor.cache_duration == "10:00:00:00") + self.assert_(isinstance(new_entity_descriptor.signature, ds.Signature)) + self.assert_(isinstance(new_entity_descriptor.extensions, md.Extensions)) + self.assert_(isinstance(new_entity_descriptor.role_descriptor[0], + md.RoleDescriptor)) + self.assert_(isinstance(new_entity_descriptor.idp_sso_descriptor[0], + md.IDPSSODescriptor)) + self.assert_(isinstance(new_entity_descriptor.sp_sso_descriptor[0], + md.SPSSODescriptor)) + self.assert_(isinstance(new_entity_descriptor.organization, + md.Organization)) + self.assert_(isinstance(new_entity_descriptor.contact_person[0], + md.ContactPerson)) + self.assert_(isinstance( + new_entity_descriptor.additional_metadata_location[0], + md.AdditionalMetadataLocation)) + + def testUsingTestData(self): + """Test for EntityDescriptorFromString() using test data.""" + new_entity_descriptor = md.EntityDescriptorFromString( + md_test_data.TEST_ENTITY_DESCRIPTOR) + self.assert_(new_entity_descriptor.id == "ID") + self.assert_(new_entity_descriptor.entity_id == "entityID") + self.assert_(new_entity_descriptor.valid_until == "2008-09-14T01:05:02Z") + self.assert_(new_entity_descriptor.cache_duration == "10:00:00:00") + self.assert_(isinstance(new_entity_descriptor.signature, ds.Signature)) + self.assert_(isinstance(new_entity_descriptor.extensions, md.Extensions)) + self.assert_(isinstance(new_entity_descriptor.role_descriptor[0], + md.RoleDescriptor)) + self.assert_(isinstance(new_entity_descriptor.idp_sso_descriptor[0], + md.IDPSSODescriptor)) + self.assert_(isinstance(new_entity_descriptor.sp_sso_descriptor[0], + md.SPSSODescriptor)) + self.assert_(isinstance(new_entity_descriptor.organization, + md.Organization)) + self.assert_(isinstance(new_entity_descriptor.contact_person[0], + md.ContactPerson)) + self.assert_(isinstance( + new_entity_descriptor.additional_metadata_location[0], + md.AdditionalMetadataLocation)) + + +class EntitiesDescriptorTest(unittest.TestCase): + def setUp(self): + self.entities_descriptor = md.EntitiesDescriptor() + + def testAccessors(self): + """Test for EntitiesDescriptor accessors""" + self.entities_descriptor.id = "ID" + self.entities_descriptor.name = "name" + self.entities_descriptor.valid_until = "2008-09-14T01:05:02Z" + self.entities_descriptor.cache_duration = "10:00:00:00" + + self.entities_descriptor.signature = ds.GetEmptySignature() + self.entities_descriptor.extensions = md.Extensions() + self.entities_descriptor.entity_descriptor.append(md.EntityDescriptor()) + self.entities_descriptor.entities_descriptor.append( + md.EntitiesDescriptor()) + + new_entities_descriptor = md.EntitiesDescriptorFromString( + self.entities_descriptor.ToString()) + self.assert_(new_entities_descriptor.id == "ID") + self.assert_(new_entities_descriptor.name == "name") + self.assert_(new_entities_descriptor.valid_until == "2008-09-14T01:05:02Z") + self.assert_(new_entities_descriptor.cache_duration == "10:00:00:00") + self.assert_(isinstance(new_entities_descriptor.signature, ds.Signature)) + self.assert_(isinstance(new_entities_descriptor.extensions, md.Extensions)) + self.assert_(isinstance(new_entities_descriptor.entity_descriptor[0], + md.EntityDescriptor)) + self.assert_(isinstance(new_entities_descriptor.entities_descriptor[0], + md.EntitiesDescriptor)) + + def testUsingTestData(self): + """Test for EntitiesDescriptorFromString() using test data.""" + new_entities_descriptor = md.EntitiesDescriptorFromString( + md_test_data.TEST_ENTITIES_DESCRIPTOR) + self.assert_(new_entities_descriptor.id == "ID") + self.assert_(new_entities_descriptor.name == "name") + self.assert_(new_entities_descriptor.valid_until == "2008-09-14T01:05:02Z") + self.assert_(new_entities_descriptor.cache_duration == "10:00:00:00") + self.assert_(isinstance(new_entities_descriptor.signature, ds.Signature)) + self.assert_(isinstance(new_entities_descriptor.extensions, md.Extensions)) + self.assert_(isinstance(new_entities_descriptor.entity_descriptor[0], + md.EntityDescriptor)) + self.assert_(isinstance(new_entities_descriptor.entities_descriptor[0], + md.EntitiesDescriptor)) + + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/saml_test.py b/tests/saml_test.py new file mode 100644 index 0000000..ab11f74 --- /dev/null +++ b/tests/saml_test.py @@ -0,0 +1,933 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for saml2.saml""" + +__author__ = 'tmatsuo@sios.com (Takashi MATSUO)' + +import unittest +try: + from xml.etree import ElementTree +except ImportError: + from elementtree import ElementTree +import saml2 +from saml2 import saml, test_data, ds_test_data +import xmldsig as ds + +class NameIDTest(unittest.TestCase): + + def setUp(self): + self.name_id = saml.NameID() + + def testEmptyExtensionsList(self): + """Test if NameID has empty extensions list""" + self.assert_(isinstance(self.name_id.extension_elements, list)) + self.assert_(len(self.name_id.extension_elements) == 0) + + def testFormatAttribute(self): + """Test for Format attribute accessors""" + self.name_id.format = saml.NAMEID_FORMAT_EMAILADDRESS + self.assert_(self.name_id.format == saml.NAMEID_FORMAT_EMAILADDRESS) + self.assert_(len(self.name_id.extension_elements) == 0) + new_name_id = saml.NameIDFromString(self.name_id.ToString()) + self.assert_(len(new_name_id.extension_elements) == 0) + + self.name_id.extension_elements.append(saml2.ExtensionElement( + 'foo', text='bar')) + self.assert_(len(self.name_id.extension_elements) == 1) + self.assert_(self.name_id.format == saml.NAMEID_FORMAT_EMAILADDRESS) + + def testNameIDText(self): + """Test text value of NameID element""" + self.name_id.text = "tmatsuo@sios.com" + self.assert_(self.name_id.text == "tmatsuo@sios.com") + + def testSPProvidedID(self): + """Test for SPProvidedID attribute accessors""" + self.name_id.sp_provided_id = "provided id" + self.assert_(self.name_id.sp_provided_id == "provided id") + + def testEmptyNameIDToAndFromStringMatch(self): + """Test NameIDFromString() with empty NameID""" + string_from_name_id = self.name_id.ToString() + new_name_id = saml.NameIDFromString(string_from_name_id) + string_from_new_name_id = new_name_id.ToString() + self.assert_(string_from_name_id == string_from_new_name_id) + + def testNameIDToAndFromStringMatch(self): + """Test NameIDFromString() with data""" + self.name_id.format = saml.NAMEID_FORMAT_EMAILADDRESS + self.name_id.text = "tmatsuo@sios.com" + self.name_id.name_qualifier = "name_qualifier" + self.name_id.sp_name_qualifier = "sp_name_qualifier" + string_from_name_id = self.name_id.ToString() + new_name_id = saml.NameIDFromString(string_from_name_id) + self.assert_(new_name_id.name_qualifier == "name_qualifier") + self.assert_(new_name_id.sp_name_qualifier == "sp_name_qualifier") + string_from_new_name_id = new_name_id.ToString() + self.assert_(string_from_name_id == string_from_new_name_id) + + def testExtensionAttributes(self): + """Test extension attributes""" + self.name_id.extension_attributes['hoge'] = 'fuga' + self.name_id.extension_attributes['moge'] = 'muga' + self.assert_(self.name_id.extension_attributes['hoge'] == 'fuga') + self.assert_(self.name_id.extension_attributes['moge'] == 'muga') + new_name_id = saml.NameIDFromString(self.name_id.ToString()) + self.assert_(new_name_id.extension_attributes['hoge'] == 'fuga') + self.assert_(new_name_id.extension_attributes['moge'] == 'muga') + + def testNameIDFromString(self): + """Test NameIDFromString() using test data""" + name_id = saml.NameIDFromString(test_data.TEST_NAME_ID) + self.assert_(name_id.format == saml.NAMEID_FORMAT_EMAILADDRESS) + self.assert_(name_id.text.strip() == "tmatsuo@sios.com") + self.assert_(name_id.sp_provided_id == "sp provided id") + + +class IssuerTest(unittest.TestCase): + + def setUp(self): + self.issuer = saml.Issuer() + + def testIssuerToAndFromString(self): + """Test IssuerFromString()""" + self.issuer.text = "http://www.sios.com/test" + self.issuer.name_qualifier = "name_qualifier" + self.issuer.sp_name_qualifier = "sp_name_qualifier" + new_issuer = saml.IssuerFromString(self.issuer.ToString()) + self.assert_(self.issuer.text == new_issuer.text) + self.assert_(self.issuer.name_qualifier == new_issuer.name_qualifier) + self.assert_(self.issuer.sp_name_qualifier == new_issuer.sp_name_qualifier) + self.assert_(self.issuer.extension_elements == + new_issuer.extension_elements) + + def testUsingTestData(self): + """Test IssuerFromString() using test data""" + issuer = saml.IssuerFromString(test_data.TEST_ISSUER) + self.assert_(issuer.text.strip() == "http://www.sios.com/test") + new_issuer = saml.IssuerFromString(issuer.ToString()) + self.assert_(issuer.text == new_issuer.text) + self.assert_(issuer.extension_elements == + new_issuer.extension_elements) + + +class SubjectLocalityTest(unittest.TestCase): + + def setUp(self): + self.subject_locality = saml.SubjectLocality() + + def testAccessors(self): + """Test for SubjectLocality accessors""" + self.subject_locality.address = "127.0.0.1" + self.subject_locality.dns_name = "localhost" + self.assert_(self.subject_locality.address == "127.0.0.1") + self.assert_(self.subject_locality.dns_name == "localhost") + new_subject_locality = saml.SubjectLocalityFromString( + self.subject_locality.ToString()) + self.assert_(new_subject_locality.address == "127.0.0.1") + self.assert_(new_subject_locality.dns_name == "localhost") + + def testUsingTestData(self): + """Test SubjectLocalityFromString() using test data""" + + subject_locality = saml.SubjectLocalityFromString( + test_data.TEST_SUBJECT_LOCALITY) + self.assert_(subject_locality.address == "127.0.0.1") + self.assert_(subject_locality.dns_name == "localhost") + + new_subject_locality = saml.SubjectLocalityFromString( + subject_locality.ToString()) + self.assert_(new_subject_locality.address == "127.0.0.1") + self.assert_(new_subject_locality.dns_name == "localhost") + self.assert_(subject_locality.ToString() == + new_subject_locality.ToString()) + + +class AuthnContextClassRefTest(unittest.TestCase): + + def setUp(self): + self.authn_context_class_ref = saml.AuthnContextClassRef() + + def testAccessors(self): + """Test for AuthnContextClassRef accessors""" + self.authn_context_class_ref.text = ( + "http://www.sios.com/authnContextClassRef") + self.assert_(self.authn_context_class_ref.text == + "http://www.sios.com/authnContextClassRef") + new_authn_context_class_ref = saml.AuthnContextClassRefFromString( + self.authn_context_class_ref.ToString()) + self.assert_(new_authn_context_class_ref.text == + "http://www.sios.com/authnContextClassRef") + + self.assert_(self.authn_context_class_ref.ToString() == + new_authn_context_class_ref.ToString()) + + def testUsingTestData(self): + """Test AuthnContextClassRefFromString() using test data""" + authn_context_class_ref = saml.AuthnContextClassRefFromString( + test_data.TEST_AUTHN_CONTEXT_CLASS_REF) + self.assert_(authn_context_class_ref.text.strip() == + "http://www.sios.com/authnContextClassRef") + + +class AuthnContextDeclRefTest(unittest.TestCase): + + def setUp(self): + self.authn_context_decl_ref = saml.AuthnContextDeclRef() + + def testAccessors(self): + """Test for AuthnContextDeclRef accessors""" + self.authn_context_decl_ref.text = ( + "http://www.sios.com/authnContextDeclRef") + self.assert_(self.authn_context_decl_ref.text == + "http://www.sios.com/authnContextDeclRef") + new_authn_context_decl_ref = saml.AuthnContextDeclRefFromString( + self.authn_context_decl_ref.ToString()) + self.assert_(new_authn_context_decl_ref.text == + "http://www.sios.com/authnContextDeclRef") + + self.assert_(self.authn_context_decl_ref.ToString() == + new_authn_context_decl_ref.ToString()) + + def testUsingTestData(self): + """Test AuthnContextDeclRefFromString() using test data""" + authn_context_decl_ref = saml.AuthnContextDeclRefFromString( + test_data.TEST_AUTHN_CONTEXT_DECL_REF) + self.assert_(authn_context_decl_ref.text.strip() == + "http://www.sios.com/authnContextDeclRef") + + +class AuthnContextDeclTest(unittest.TestCase): + + def setUp(self): + self.authn_context_decl = saml.AuthnContextDecl() + + def testAccessors(self): + """Test for AuthnContextDecl accessors""" + self.authn_context_decl.text = ( + "http://www.sios.com/authnContextDecl") + self.assert_(self.authn_context_decl.text == + "http://www.sios.com/authnContextDecl") + new_authn_context_decl = saml.AuthnContextDeclFromString( + self.authn_context_decl.ToString()) + self.assert_(new_authn_context_decl.text == + "http://www.sios.com/authnContextDecl") + + self.assert_(self.authn_context_decl.ToString() == + new_authn_context_decl.ToString()) + + def testUsingTestData(self): + """Test AuthnContextDeclFromString() using test data""" + authn_context_decl = saml.AuthnContextDeclFromString( + test_data.TEST_AUTHN_CONTEXT_DECL) + self.assert_(authn_context_decl.text.strip() == + "http://www.sios.com/authnContextDecl") + + +class AuthenticatingAuthorityTest(unittest.TestCase): + + def setUp(self): + self.authenticating_authority = saml.AuthenticatingAuthority() + + def testAccessors(self): + """Test for AuthenticatingAuthority accessors""" + self.authenticating_authority.text = ( + "http://www.sios.com/authenticatingAuthority") + self.assert_(self.authenticating_authority.text == + "http://www.sios.com/authenticatingAuthority") + new_authenticating_authority = saml.AuthenticatingAuthorityFromString( + self.authenticating_authority.ToString()) + self.assert_(new_authenticating_authority.text == + "http://www.sios.com/authenticatingAuthority") + + self.assert_(self.authenticating_authority.ToString() == + new_authenticating_authority.ToString()) + + def testUsingTestData(self): + """Test AuthenticatingAuthorityFromString() using test data""" + authenticating_authority = saml.AuthenticatingAuthorityFromString( + test_data.TEST_AUTHENTICATING_AUTHORITY) + self.assert_(authenticating_authority.text.strip() == + "http://www.sios.com/authenticatingAuthority") + + +class AuthnContextTest(unittest.TestCase): + + def setUp(self): + self.authn_context = saml.AuthnContext() + + def testAccessors(self): + """Test for AuthnContext accessors""" + self.authn_context.authn_context_class_ref = \ + saml.AuthnContextClassRefFromString( + test_data.TEST_AUTHN_CONTEXT_CLASS_REF) + self.authn_context.authn_context_decl_ref = \ + saml.AuthnContextDeclRefFromString( + test_data.TEST_AUTHN_CONTEXT_DECL_REF) + self.authn_context.authn_context_decl = \ + saml.AuthnContextDeclFromString( + test_data.TEST_AUTHN_CONTEXT_DECL) + self.authn_context.authenticating_authority.append( + saml.AuthenticatingAuthorityFromString( + test_data.TEST_AUTHENTICATING_AUTHORITY)) + self.assert_(self.authn_context.authn_context_class_ref.text.strip() == + "http://www.sios.com/authnContextClassRef") + self.assert_(self.authn_context.authn_context_decl_ref.text.strip() == + "http://www.sios.com/authnContextDeclRef") + self.assert_(self.authn_context.authn_context_decl.text.strip() == + "http://www.sios.com/authnContextDecl") + self.assert_(self.authn_context.authenticating_authority[0].text.strip() == + "http://www.sios.com/authenticatingAuthority") + new_authn_context = saml.AuthnContextFromString( + self.authn_context.ToString()) + self.assert_(self.authn_context.ToString() == new_authn_context.ToString()) + + def testUsingTestData(self): + """Test AuthnContextFromString() using test data""" + authn_context = saml.AuthnContextFromString(test_data.TEST_AUTHN_CONTEXT) + self.assert_(authn_context.authn_context_class_ref.text.strip() == + saml.URN_PASSWORD) + + +class AuthnStatementTest(unittest.TestCase): + + def setUp(self): + self.as = saml.AuthnStatement() + + def testAccessors(self): + """Test for AuthnStatement accessors""" + self.as.authn_instant = "2007-08-31T01:05:02Z" + self.as.session_not_on_or_after = "2007-09-14T01:05:02Z" + self.as.session_index = "sessionindex" + self.as.authn_context = saml.AuthnContext() + self.as.authn_context.authn_context_class_ref = \ + saml.AuthnContextClassRefFromString( + test_data.TEST_AUTHN_CONTEXT_CLASS_REF) + self.as.authn_context.authn_context_decl_ref = \ + saml.AuthnContextDeclRefFromString( + test_data.TEST_AUTHN_CONTEXT_DECL_REF) + self.as.authn_context.authn_context_decl = \ + saml.AuthnContextDeclFromString( + test_data.TEST_AUTHN_CONTEXT_DECL) + self.as.authn_context.authenticating_authority.append( + saml.AuthenticatingAuthorityFromString( + test_data.TEST_AUTHENTICATING_AUTHORITY)) + + new_as = saml.AuthnStatementFromString(self.as.ToString()) + self.assert_(new_as.authn_instant == "2007-08-31T01:05:02Z") + self.assert_(new_as.session_index == "sessionindex") + self.assert_(new_as.session_not_on_or_after == "2007-09-14T01:05:02Z") + self.assert_(new_as.authn_context.authn_context_class_ref.text.strip() == + "http://www.sios.com/authnContextClassRef") + self.assert_(new_as.authn_context.authn_context_decl_ref.text.strip() == + "http://www.sios.com/authnContextDeclRef") + self.assert_(new_as.authn_context.authn_context_decl.text.strip() == + "http://www.sios.com/authnContextDecl") + self.assert_(new_as.authn_context.authenticating_authority[0].text.strip() + == "http://www.sios.com/authenticatingAuthority") + self.assert_(self.as.ToString() == new_as.ToString()) + + def testUsingTestData(self): + """Test AuthnStatementFromString() using test data""" + as = saml.AuthnStatementFromString(test_data.TEST_AUTHN_STATEMENT) + self.assert_(as.authn_instant == "2007-08-31T01:05:02Z") + self.assert_(as.session_not_on_or_after == "2007-09-14T01:05:02Z") + self.assert_(as.authn_context.authn_context_class_ref.text.strip() == + saml.URN_PASSWORD) + + +class AttributeValueTest(unittest.TestCase): + + def setUp(self): + self.attribute_value = saml.AttributeValue() + + def testAccessors(self): + """Test for AttributeValue accessors""" + + self.attribute_value.text = "value for test attribute" + new_attribute_value = saml.AttributeValueFromString( + self.attribute_value.ToString()) + self.assert_(new_attribute_value.text.strip() == + "value for test attribute") + + def testUsingTestData(self): + """Test AttributeValueFromString() using test data""" + + attribute_value = saml.AttributeValueFromString( + test_data.TEST_ATTRIBUTE_VALUE) + self.assert_(attribute_value.text.strip() == "value for test attribute") + + +class AttributeTest(unittest.TestCase): + + def setUp(self): + self.attribute = saml.Attribute() + + def testAccessors(self): + """Test for Attribute accessors""" + self.attribute.name = "testAttribute" + self.attribute.name_format = saml.NAME_FORMAT_URI + self.attribute.friendly_name = "test attribute" + self.attribute.attribute_value.append(saml.AttributeValue()) + self.attribute.attribute_value[0].text = "value of test attribute" + + new_attribute = saml.AttributeFromString(self.attribute.ToString()) + self.assert_(new_attribute.name == "testAttribute") + self.assert_(new_attribute.name_format == saml.NAME_FORMAT_URI) + self.assert_(new_attribute.friendly_name == "test attribute") + self.assert_(new_attribute.attribute_value[0].text.strip() == + "value of test attribute") + + def testUsingTestData(self): + """Test AttributeFromString() using test data""" + attribute = saml.AttributeFromString(test_data.TEST_ATTRIBUTE) + self.assert_(attribute.name == "testAttribute") + self.assert_(attribute.name_format == saml.NAME_FORMAT_UNSPECIFIED) + self.assert_(attribute.friendly_name == "test attribute") + self.assert_(attribute.attribute_value[0].text.strip() == + "value1 of test attribute") + self.assert_(attribute.attribute_value[1].text.strip() == + "value2 of test attribute") + # test again + attribute = saml.AttributeFromString(attribute.ToString()) + self.assert_(attribute.name == "testAttribute") + self.assert_(attribute.name_format == saml.NAME_FORMAT_UNSPECIFIED) + self.assert_(attribute.friendly_name == "test attribute") + self.assert_(attribute.attribute_value[0].text.strip() == + "value1 of test attribute") + self.assert_(attribute.attribute_value[1].text.strip() == + "value2 of test attribute") + + +class AttributeStatementTest(unittest.TestCase): + + def setUp(self): + self.as = saml.AttributeStatement() + + def testAccessors(self): + """Test for Attribute accessors""" + self.as.attribute.append(saml.Attribute()) + self.as.attribute.append(saml.Attribute()) + self.as.attribute[0].name = "testAttribute" + self.as.attribute[0].name_format = saml.NAME_FORMAT_URI + self.as.attribute[0].friendly_name = "test attribute" + self.as.attribute[0].attribute_value.append(saml.AttributeValue()) + self.as.attribute[0].attribute_value[0].text = "value of test attribute" + + self.as.attribute[1].name = "testAttribute2" + self.as.attribute[1].name_format = saml.NAME_FORMAT_UNSPECIFIED + self.as.attribute[1].friendly_name = "test attribute2" + self.as.attribute[1].attribute_value.append(saml.AttributeValue()) + self.as.attribute[1].attribute_value[0].text = "value2 of test attribute" + + new_as = saml.AttributeStatementFromString(self.as.ToString()) + self.assert_(new_as.attribute[0].name == "testAttribute") + self.assert_(new_as.attribute[0].name_format == saml.NAME_FORMAT_URI) + self.assert_(new_as.attribute[0].friendly_name == "test attribute") + self.assert_(new_as.attribute[0].attribute_value[0].text.strip() == + "value of test attribute") + self.assert_(new_as.attribute[1].name == "testAttribute2") + self.assert_(new_as.attribute[1].name_format == + saml.NAME_FORMAT_UNSPECIFIED) + self.assert_(new_as.attribute[1].friendly_name == "test attribute2") + self.assert_(new_as.attribute[1].attribute_value[0].text.strip() == + "value2 of test attribute") + + def testUsingTestData(self): + """Test AttributeStatementFromString() using test data""" + as = saml.AttributeStatementFromString(test_data.TEST_ATTRIBUTE_STATEMENT) + self.assert_(as.attribute[0].name == "testAttribute") + self.assert_(as.attribute[0].name_format == saml.NAME_FORMAT_UNSPECIFIED) + self.assert_(as.attribute[0].friendly_name == "test attribute") + self.assert_(as.attribute[0].attribute_value[0].text.strip() == + "value1 of test attribute") + self.assert_(as.attribute[0].attribute_value[1].text.strip() == + "value2 of test attribute") + self.assert_(as.attribute[1].name == "http://www.sios.com/testAttribute2") + self.assert_(as.attribute[1].name_format == saml.NAME_FORMAT_URI) + self.assert_(as.attribute[1].friendly_name == "test attribute2") + self.assert_(as.attribute[1].attribute_value[0].text.strip() == + "value1 of test attribute2") + self.assert_(as.attribute[1].attribute_value[1].text.strip() == + "value2 of test attribute2") + + # test again + as = saml.AttributeStatementFromString(as.ToString()) + self.assert_(as.attribute[0].name == "testAttribute") + self.assert_(as.attribute[0].name_format == saml.NAME_FORMAT_UNSPECIFIED) + self.assert_(as.attribute[0].friendly_name == "test attribute") + self.assert_(as.attribute[0].attribute_value[0].text.strip() == + "value1 of test attribute") + self.assert_(as.attribute[0].attribute_value[1].text.strip() == + "value2 of test attribute") + self.assert_(as.attribute[1].name == "http://www.sios.com/testAttribute2") + self.assert_(as.attribute[1].name_format == saml.NAME_FORMAT_URI) + self.assert_(as.attribute[1].friendly_name == "test attribute2") + self.assert_(as.attribute[1].attribute_value[0].text.strip() == + "value1 of test attribute2") + self.assert_(as.attribute[1].attribute_value[1].text.strip() == + "value2 of test attribute2") + + +class SubjectConfirmationDataTest(unittest.TestCase): + + def setUp(self): + self.scd = saml.SubjectConfirmationData() + + def testAccessors(self): + """Test for SubjectConfirmationData accessors""" + + self.scd.not_before = "2007-08-31T01:05:02Z" + self.scd.not_on_or_after = "2007-09-14T01:05:02Z" + self.scd.recipient = "recipient" + self.scd.in_response_to = "responseID" + self.scd.address = "127.0.0.1" + new_scd = saml.SubjectConfirmationDataFromString(self.scd.ToString()) + self.assert_(new_scd.not_before == "2007-08-31T01:05:02Z") + self.assert_(new_scd.not_on_or_after == "2007-09-14T01:05:02Z") + self.assert_(new_scd.recipient == "recipient") + self.assert_(new_scd.in_response_to == "responseID") + self.assert_(new_scd.address == "127.0.0.1") + + def testUsingTestData(self): + """Test SubjectConfirmationDataFromString() using test data""" + + scd = saml.SubjectConfirmationDataFromString( + test_data.TEST_SUBJECT_CONFIRMATION_DATA) + self.assert_(scd.not_before == "2007-08-31T01:05:02Z") + self.assert_(scd.not_on_or_after == "2007-09-14T01:05:02Z") + self.assert_(scd.recipient == "recipient") + self.assert_(scd.in_response_to == "responseID") + self.assert_(scd.address == "127.0.0.1") + + +class SubjectConfirmationTest(unittest.TestCase): + + def setUp(self): + self.sc = saml.SubjectConfirmation() + + def testAccessors(self): + """Test for SubjectConfirmation accessors""" + self.sc.name_id = saml.NameIDFromString(test_data.TEST_NAME_ID) + self.sc.method = saml.SUBJECT_CONFIRMATION_METHOD_BEARER + self.sc.subject_confirmation_data = saml.SubjectConfirmationDataFromString( + test_data.TEST_SUBJECT_CONFIRMATION_DATA) + new_sc = saml.SubjectConfirmationFromString(self.sc.ToString()) + self.assert_(new_sc.name_id.sp_provided_id == "sp provided id") + self.assert_(new_sc.method == saml.SUBJECT_CONFIRMATION_METHOD_BEARER) + self.assert_(new_sc.subject_confirmation_data.not_before == + "2007-08-31T01:05:02Z") + self.assert_(new_sc.subject_confirmation_data.not_on_or_after == + "2007-09-14T01:05:02Z") + self.assert_(new_sc.subject_confirmation_data.recipient == "recipient") + self.assert_(new_sc.subject_confirmation_data.in_response_to == + "responseID") + self.assert_(new_sc.subject_confirmation_data.address == "127.0.0.1") + + def testUsingTestData(self): + """Test SubjectConfirmationFromString() using test data""" + + sc = saml.SubjectConfirmationFromString( + test_data.TEST_SUBJECT_CONFIRMATION) + self.assert_(sc.name_id.sp_provided_id == "sp provided id") + self.assert_(sc.method == saml.SUBJECT_CONFIRMATION_METHOD_BEARER) + self.assert_(sc.subject_confirmation_data.not_before == + "2007-08-31T01:05:02Z") + self.assert_(sc.subject_confirmation_data.not_on_or_after == + "2007-09-14T01:05:02Z") + self.assert_(sc.subject_confirmation_data.recipient == "recipient") + self.assert_(sc.subject_confirmation_data.in_response_to == + "responseID") + self.assert_(sc.subject_confirmation_data.address == "127.0.0.1") + + +class SubjectTest(unittest.TestCase): + + def setUp(self): + self.subject = saml.Subject() + + def testAccessors(self): + """Test for Subject accessors""" + self.subject.name_id = saml.NameIDFromString(test_data.TEST_NAME_ID) + self.subject.subject_confirmation.append( + saml.SubjectConfirmationFromString( + test_data.TEST_SUBJECT_CONFIRMATION)) + new_subject = saml.SubjectFromString(self.subject.ToString()) + self.assert_(new_subject.name_id.sp_provided_id == "sp provided id") + self.assert_(new_subject.name_id.text.strip() == "tmatsuo@sios.com") + self.assert_(new_subject.name_id.format == + saml.NAMEID_FORMAT_EMAILADDRESS) + self.assert_(isinstance(new_subject.subject_confirmation[0], + saml.SubjectConfirmation)) + + def testUsingTestData(self): + """Test for SubjectFromString() using test data.""" + + subject = saml.SubjectFromString(test_data.TEST_SUBJECT) + self.assert_(subject.name_id.sp_provided_id == "sp provided id") + self.assert_(subject.name_id.text.strip() == "tmatsuo@sios.com") + self.assert_(subject.name_id.format == + saml.NAMEID_FORMAT_EMAILADDRESS) + self.assert_(isinstance(subject.subject_confirmation[0], + saml.SubjectConfirmation)) + + +class ConditionTest(unittest.TestCase): + + def setUp(self): + self.condition = saml.Condition() + + def testAccessors(self): + """Test for Condition accessors.""" + self.condition.extension_attributes["{%s}type" % saml.XSI_NAMESPACE] = \ + "test" + self.condition.extension_attributes['ExtendedAttribute'] = "value" + new_condition = saml.ConditionFromString(self.condition.ToString()) + self.assert_( + new_condition.extension_attributes["{%s}type" % saml.XSI_NAMESPACE] == + "test") + self.assert_(new_condition.extension_attributes["ExtendedAttribute"] == + "value") + + def testUsingTestData(self): + """Test for ConditionFromString() using test data.""" + + condition = saml.ConditionFromString(test_data.TEST_CONDITION) + self.assert_( + condition.extension_attributes["{%s}type" % saml.XSI_NAMESPACE] == + "test") + self.assert_(condition.extension_attributes["ExtendedAttribute"] == + "value") + + +class AudienceTest(unittest.TestCase): + + def setUp(self): + self.audience = saml.Audience() + + def testAccessors(self): + """Test for Audience accessors""" + + self.audience.text = "http://www.sios.com/Audience" + new_audience = saml.AudienceFromString(self.audience.ToString()) + self.assert_(new_audience.text.strip() == "http://www.sios.com/Audience") + + def testUsingTestData(self): + """Test AudienceFromString using test data""" + + audience = saml.AudienceFromString(test_data.TEST_AUDIENCE) + self.assert_(audience.text.strip() == "http://www.sios.com/Audience") + + +class AudienceRestrictionTest(unittest.TestCase): + def setUp(self): + self.audience_restriction = saml.AudienceRestriction() + + def testAccessors(self): + """Test for AudienceRestriction accessors""" + + self.audience_restriction.audience = saml.AudienceFromString( + test_data.TEST_AUDIENCE) + new_audience = saml.AudienceRestrictionFromString( + self.audience_restriction.ToString()) + self.assert_(self.audience_restriction.audience.text.strip() == + "http://www.sios.com/Audience") + + def testUsingTestData(self): + """Test AudienceRestrictionFromString using test data""" + + audience_restriction = saml.AudienceRestrictionFromString( + test_data.TEST_AUDIENCE_RESTRICTION) + self.assert_(audience_restriction.audience.text.strip() == + "http://www.sios.com/Audience") + + +class OneTimeUseTest(unittest.TestCase): + + def setUp(self): + self.one_time_use = saml.OneTimeUse() + + def testAccessors(self): + """Test for OneTimeUse accessors""" + self.assert_(isinstance(self.one_time_use, saml.OneTimeUse)) + self.assert_(isinstance(self.one_time_use, saml.Condition)) + + def testUsingTestData(self): + """Test OneTimeUseFromString() using test data""" + one_time_use = saml.OneTimeUseFromString(test_data.TEST_ONE_TIME_USE) + self.assert_(isinstance(one_time_use, saml.OneTimeUse)) + self.assert_(isinstance(one_time_use, saml.Condition)) + + +class ProxyRestrictionTest(unittest.TestCase): + + def setUp(self): + self.proxy_restriction = saml.ProxyRestriction() + + def testAccessors(self): + """Test for ProxyRestriction accessors""" + + self.assert_(isinstance(self.proxy_restriction, saml.Condition)) + self.proxy_restriction.count = "2" + self.proxy_restriction.audience.append(saml.AudienceFromString( + test_data.TEST_AUDIENCE)) + new_proxy_restriction = saml.ProxyRestrictionFromString( + self.proxy_restriction.ToString()) + self.assert_(new_proxy_restriction.count == "2") + self.assert_(new_proxy_restriction.audience[0].text.strip() == + "http://www.sios.com/Audience") + + def testUsingTestData(self): + """Test ProxyRestrictionFromString() using test data""" + + proxy_restriction = saml.ProxyRestrictionFromString( + test_data.TEST_PROXY_RESTRICTION) + self.assert_(proxy_restriction.count == "2") + self.assert_(proxy_restriction.audience[0].text.strip() == + "http://www.sios.com/Audience") + +class ConditionsTest(unittest.TestCase): + + def setUp(self): + self.conditions = saml.Conditions() + + def testAccessors(self): + """Test for Conditions accessors""" + self.conditions.not_before = "2007-08-31T01:05:02Z" + self.conditions.not_on_or_after = "2007-09-14T01:05:02Z" + self.conditions.condition.append(saml.Condition()) + self.conditions.audience_restriction.append(saml.AudienceRestriction()) + self.conditions.one_time_use.append(saml.OneTimeUse()) + self.conditions.proxy_restriction.append(saml.ProxyRestriction()) + new_conditions = saml.ConditionsFromString(self.conditions.ToString()) + self.assert_(new_conditions.not_before == "2007-08-31T01:05:02Z") + self.assert_(new_conditions.not_on_or_after == "2007-09-14T01:05:02Z") + self.assert_(isinstance(new_conditions.condition[0], saml.Condition)) + self.assert_(isinstance(new_conditions.audience_restriction[0], + saml.AudienceRestriction)) + self.assert_(isinstance(new_conditions.one_time_use[0], + saml.OneTimeUse)) + self.assert_(isinstance(new_conditions.proxy_restriction[0], + saml.ProxyRestriction)) + + def testUsingTestData(self): + """Test ConditionsFromString() using test data""" + new_conditions = saml.ConditionsFromString(test_data.TEST_CONDITIONS) + self.assert_(new_conditions.not_before == "2007-08-31T01:05:02Z") + self.assert_(new_conditions.not_on_or_after == "2007-09-14T01:05:02Z") + self.assert_(isinstance(new_conditions.condition[0], saml.Condition)) + self.assert_(isinstance(new_conditions.audience_restriction[0], + saml.AudienceRestriction)) + self.assert_(isinstance(new_conditions.one_time_use[0], + saml.OneTimeUse)) + self.assert_(isinstance(new_conditions.proxy_restriction[0], + saml.ProxyRestriction)) + +class AssertionIDRefTest(unittest.TestCase): + + def setUp(self): + self.assertion_id_ref = saml.AssertionIDRef() + + def testAccessors(self): + """Test for AssertionIDRef accessors""" + self.assertion_id_ref.text = "zzlieajngjbkjggjldmgindkckkolcblndbghlhm" + new_assertion_id_ref = saml.AssertionIDRefFromString( + self.assertion_id_ref.ToString()) + self.assert_(new_assertion_id_ref.text == + "zzlieajngjbkjggjldmgindkckkolcblndbghlhm") + + def testUsingTestData(self): + """Test AssertionIDRefFromString() using test data""" + new_assertion_id_ref = saml.AssertionIDRefFromString( + test_data.TEST_ASSERTION_ID_REF) + self.assert_(new_assertion_id_ref.text.strip() == + "zzlieajngjbkjggjldmgindkckkolcblndbghlhm") + + +class AssertionURIRefTest(unittest.TestCase): + + def setUp(self): + self.assertion_uri_ref = saml.AssertionURIRef() + + def testAccessors(self): + """Test for AssertionURIRef accessors""" + self.assertion_uri_ref.text = "http://www.sios.com/AssertionURIRef" + new_assertion_uri_ref = saml.AssertionURIRefFromString( + self.assertion_uri_ref.ToString()) + self.assert_(new_assertion_uri_ref.text == + "http://www.sios.com/AssertionURIRef") + + def testUsingTestData(self): + """Test AssertionURIRefFromString() using test data""" + new_assertion_uri_ref = saml.AssertionURIRefFromString( + test_data.TEST_ASSERTION_URI_REF) + self.assert_(new_assertion_uri_ref.text.strip() == + "http://www.sios.com/AssertionURIRef") + + +class ActionTest(unittest.TestCase): + + def setUp(self): + self.action = saml.Action() + + def testAccessors(self): + """Test for Action accessors""" + self.action.namespace = "http://www.sios.com/Namespace" + new_action = saml.ActionFromString(self.action.ToString()) + self.assert_(new_action.namespace == "http://www.sios.com/Namespace") + + def testUsingTestData(self): + """Test ActionFromString() using test data""" + new_action = saml.ActionFromString(test_data.TEST_ACTION) + self.assert_(new_action.namespace == "http://www.sios.com/Namespace") + + +class EvidenceTest(unittest.TestCase): + + def setUp(self): + self.evidence = saml.Evidence() + + def testAccessors(self): + """Test for Evidence accessors""" + self.evidence.assertion_id_ref.append(saml.AssertionIDRef()) + self.evidence.assertion_uri_ref.append(saml.AssertionURIRef()) + self.evidence.assertion.append(saml.Assertion()) + self.evidence.encrypted_assertion.append(saml.EncryptedAssertion()) + new_evidence = saml.EvidenceFromString(self.evidence.ToString()) + self.assert_(self.evidence.ToString() == new_evidence.ToString()) + self.assert_(isinstance(new_evidence.assertion_id_ref[0], + saml.AssertionIDRef)) + self.assert_(isinstance(new_evidence.assertion_uri_ref[0], + saml.AssertionURIRef)) + self.assert_(isinstance(new_evidence.assertion[0], saml.Assertion)) + self.assert_(isinstance(new_evidence.encrypted_assertion[0], + saml.EncryptedAssertion)) + + def testUsingTestData(self): + """Test EvidenceFromString() using test data""" + # TODO: + pass + + +class AuthzDecisionStatementTest(unittest.TestCase): + + def setUp(self): + self.authz_decision_statement = saml.AuthzDecisionStatement() + + def testAccessors(self): + """Test for AuthzDecisionStatement accessors""" + self.authz_decision_statement.resource = "http://www.sios.com/Resource" + self.authz_decision_statement.decision = saml.DECISION_TYPE_PERMIT + self.authz_decision_statement.action.append(saml.Action()) + self.authz_decision_statement.evidence.append(saml.Evidence()) + new_authz_decision_statement = saml.AuthzDecisionStatementFromString( + self.authz_decision_statement.ToString()) + self.assert_(self.authz_decision_statement.ToString() == + new_authz_decision_statement.ToString()) + self.assert_(new_authz_decision_statement.resource == + "http://www.sios.com/Resource") + self.assert_(new_authz_decision_statement.decision == + saml.DECISION_TYPE_PERMIT) + self.assert_(isinstance(new_authz_decision_statement.action[0], + saml.Action)) + self.assert_(isinstance(new_authz_decision_statement.evidence[0], + saml.Evidence)) + + + def testUsingTestData(self): + """Test AuthzDecisionStatementFromString() using test data""" + # TODO: + pass + +class AdviceTest(unittest.TestCase): + + def setUp(self): + self.advice = saml.Advice() + + def testAccessors(self): + """Test for Advice accessors""" + self.advice.assertion_id_ref.append(saml.AssertionIDRef()) + self.advice.assertion_uri_ref.append(saml.AssertionURIRef()) + self.advice.assertion.append(saml.Assertion()) + self.advice.encrypted_assertion.append(saml.EncryptedAssertion()) + new_advice = saml.AdviceFromString(self.advice.ToString()) + self.assert_(self.advice.ToString() == new_advice.ToString()) + self.assert_(isinstance(new_advice.assertion_id_ref[0], + saml.AssertionIDRef)) + self.assert_(isinstance(new_advice.assertion_uri_ref[0], + saml.AssertionURIRef)) + self.assert_(isinstance(new_advice.assertion[0], saml.Assertion)) + self.assert_(isinstance(new_advice.encrypted_assertion[0], + saml.EncryptedAssertion)) + + def testUsingTestData(self): + """Test AdviceFromString() using test data""" + # TODO: + pass + + +class AssertionTest(unittest.TestCase): + + def setUp(self): + self.assertion = saml.Assertion() + + def testAccessors(self): + """Test for Assertion accessors""" + self.assertion.id = "assertion id" + self.assertion.version = saml.V2 + self.assertion.issue_instant = "2007-08-31T01:05:02Z" + self.assertion.issuer = saml.IssuerFromString(test_data.TEST_ISSUER) + self.assertion.signature = ds.SignatureFromString( + ds_test_data.TEST_SIGNATURE) + self.assertion.subject = saml.SubjectFromString(test_data.TEST_SUBJECT) + self.assertion.conditions = saml.ConditionsFromString( + test_data.TEST_CONDITIONS) + self.assertion.advice = saml.Advice() + self.assertion.statement.append(saml.Statement()) + self.assertion.authn_statement.append(saml.AuthnStatementFromString( + test_data.TEST_AUTHN_STATEMENT)) + self.assertion.authz_decision_statement.append( + saml.AuthzDecisionStatement()) + self.assertion.attribute_statement.append( + saml.AttributeStatementFromString( + test_data.TEST_ATTRIBUTE_STATEMENT)) + + new_assertion = saml.AssertionFromString(self.assertion.ToString()) + self.assert_(new_assertion.id == "assertion id") + self.assert_(new_assertion.version == saml.V2) + self.assert_(new_assertion.issue_instant == "2007-08-31T01:05:02Z") + self.assert_(isinstance(new_assertion.issuer, saml.Issuer)) + self.assert_(isinstance(new_assertion.signature, ds.Signature)) + self.assert_(isinstance(new_assertion.subject, saml.Subject)) + self.assert_(isinstance(new_assertion.conditions, saml.Conditions)) + self.assert_(isinstance(new_assertion.advice, saml.Advice)) + self.assert_(isinstance(new_assertion.statement[0], saml.Statement)) + self.assert_(isinstance(new_assertion.authn_statement[0], + saml.AuthnStatement)) + self.assert_(isinstance(new_assertion.authz_decision_statement[0], + saml.AuthzDecisionStatement)) + self.assert_(isinstance(new_assertion.attribute_statement[0], + saml.AttributeStatement)) + + + def testUsingTestData(self): + """Test AssertionFromString() using test data""" + # TODO + pass + +if __name__ == '__main__': + unittest.main() diff --git a/tests/samlp_test.py b/tests/samlp_test.py new file mode 100644 index 0000000..15cb83c --- /dev/null +++ b/tests/samlp_test.py @@ -0,0 +1,535 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for saml2.samlp""" + +__author__ = 'tmatsuo@sios.com (Takashi MATSUO)' + +import unittest +try: + from xml.etree import ElementTree +except ImportError: + from elementtree import ElementTree +import saml2 +from saml2 import saml, samlp, test_data, ds_test_data, samlp_test_data +import xmldsig as ds + + +class AbstractRequestTest(unittest.TestCase): + + def setUp(self): + self.ar = samlp.AbstractRequest() + + def testAccessors(self): + """Test for AbstractRequest accessors""" + self.ar.id = "request id" + self.ar.version = saml.V2 + self.ar.issue_instant = "2007-09-14T01:05:02Z" + self.ar.destination = "http://www.sios.com/Destination" + self.ar.consent = saml.CONSENT_UNSPECIFIED + self.ar.issuer = saml.Issuer() + self.ar.signature = ds.GetEmptySignature() + self.ar.extensions = samlp.Extensions() + + new_ar = samlp.AbstractRequestFromString(self.ar.ToString()) + self.assert_(new_ar.id == "request id") + self.assert_(new_ar.version == saml.V2) + self.assert_(new_ar.issue_instant == "2007-09-14T01:05:02Z") + self.assert_(new_ar.destination == "http://www.sios.com/Destination") + self.assert_(new_ar.consent == saml.CONSENT_UNSPECIFIED) + self.assert_(isinstance(new_ar.issuer, saml.Issuer)) + self.assert_(isinstance(new_ar.signature, ds.Signature)) + self.assert_(isinstance(new_ar.extensions, samlp.Extensions)) + + def testUsingTestData(self): + """Test for AbstractRequestFromString() using test data""" + # TODO: + pass + +class StatusDetailTest(unittest.TestCase): + + def setUp(self): + self.status_detail = samlp.StatusDetail() + + def testAccessors(self): + """Test for StatusDetail accessors""" + # TODO: + pass + + +class StatusMessageTest(unittest.TestCase): + + def setUp(self): + self.status_message = samlp.StatusMessage() + + def testAccessors(self): + """Test for StatusMessage accessors""" + # TODO: + pass + + +class StatusCodeTest(unittest.TestCase): + + def setUp(self): + self.status_code = samlp.StatusCode() + + def testAccessors(self): + """Test for StatusCode accessors""" + self.status_code.value = samlp.STATUS_RESPONDER + self.status_code.status_code = samlp.StatusCode( + value=samlp.STATUS_REQUEST_DENIED) + new_status_code = samlp.StatusCodeFromString(self.status_code.ToString()) + self.assert_(new_status_code.value == samlp.STATUS_RESPONDER) + self.assert_(new_status_code.status_code.value == + samlp.STATUS_REQUEST_DENIED) + + def testUsingTestData(self): + """Test for StatusCodeFromString() using test data""" + new_status_code = samlp.StatusCodeFromString( + samlp_test_data.TEST_STATUS_CODE) + self.assert_(new_status_code.value == samlp.STATUS_RESPONDER) + self.assert_(new_status_code.status_code.value == + samlp.STATUS_REQUEST_DENIED) + + +class StatusTest(unittest.TestCase): + + def setUp(self): + self.status = samlp.Status() + + def testAccessors(self): + """Test for Status accessors""" + self.status.status_code = samlp.StatusCode() + self.status.status_message = samlp.StatusMessage() + self.status.status_detail = samlp.StatusDetail() + new_status = samlp.StatusFromString(self.status.ToString()) + self.assert_(isinstance(new_status.status_code, samlp.StatusCode)) + self.assert_(isinstance(new_status.status_message, samlp.StatusMessage)) + self.assert_(isinstance(new_status.status_detail, samlp.StatusDetail)) + + def testUsingTestData(self): + """Test for StatusFromString using test data""" + new_status = samlp.StatusFromString(samlp_test_data.TEST_STATUS) + self.assert_(isinstance(new_status.status_code, samlp.StatusCode)) + self.assert_(isinstance(new_status.status_code.status_code, + samlp.StatusCode)) + self.assert_(isinstance(new_status.status_message, samlp.StatusMessage)) + self.assert_(isinstance(new_status.status_detail, samlp.StatusDetail)) + +class StatusResponseTest(unittest.TestCase): + + def setUp(self): + self.sr = samlp.StatusResponse() + + def testAccessors(self): + """Test for StatusResponse accessors""" + self.sr.id = "response id" + self.sr.in_response_to = "request id" + self.sr.version = saml.V2 + self.sr.issue_instant = "2007-09-14T01:05:02Z" + self.sr.destination = "http://www.sios.com/Destination" + self.sr.consent = saml.CONSENT_UNSPECIFIED + self.sr.issuer = saml.Issuer() + self.sr.signature = ds.GetEmptySignature() + self.sr.extensions = samlp.Extensions() + self.sr.status = samlp.Status() + + new_sr = samlp.StatusResponseFromString(self.sr.ToString()) + self.assert_(new_sr.id == "response id") + self.assert_(new_sr.in_response_to == "request id") + self.assert_(new_sr.version == saml.V2) + self.assert_(new_sr.issue_instant == "2007-09-14T01:05:02Z") + self.assert_(new_sr.destination == "http://www.sios.com/Destination") + self.assert_(new_sr.consent == saml.CONSENT_UNSPECIFIED) + self.assert_(isinstance(new_sr.issuer, saml.Issuer)) + self.assert_(isinstance(new_sr.signature, ds.Signature)) + self.assert_(isinstance(new_sr.extensions, samlp.Extensions)) + self.assert_(isinstance(new_sr.status, samlp.Status)) + + def testUsingTestData(self): + """Test for StatusResponseFromString() using test data""" + # TODO: + pass + + +class ResponseTest(unittest.TestCase): + + def setUp(self): + self.response = samlp.Response() + + def testAccessors(self): + """Test for Response accessors""" + self.response.id = "response id" + self.response.in_response_to = "request id" + self.response.version = saml.V2 + self.response.issue_instant = "2007-09-14T01:05:02Z" + self.response.destination = "http://www.sios.com/Destination" + self.response.consent = saml.CONSENT_UNSPECIFIED + self.response.issuer = saml.Issuer() + self.response.signature = ds.GetEmptySignature() + self.response.extensions = samlp.Extensions() + self.response.status = samlp.Status() + self.response.assertion.append(saml.Assertion()) + self.response.encrypted_assertion.append(saml.EncryptedAssertion()) + + new_response = samlp.ResponseFromString(self.response.ToString()) + self.assert_(new_response.id == "response id") + self.assert_(new_response.in_response_to == "request id") + self.assert_(new_response.version == saml.V2) + self.assert_(new_response.issue_instant == "2007-09-14T01:05:02Z") + self.assert_(new_response.destination == "http://www.sios.com/Destination") + self.assert_(new_response.consent == saml.CONSENT_UNSPECIFIED) + self.assert_(isinstance(new_response.issuer, saml.Issuer)) + self.assert_(isinstance(new_response.signature, ds.Signature)) + self.assert_(isinstance(new_response.extensions, samlp.Extensions)) + self.assert_(isinstance(new_response.status, samlp.Status)) + + self.assert_(isinstance(new_response.assertion[0], saml.Assertion)) + self.assert_(isinstance(new_response.encrypted_assertion[0], + saml.EncryptedAssertion)) + + def testUsingTestData(self): + """Test for ResponseFromString() using test data""" + # TODO: + pass + +class NameIDPolicyTest(unittest.TestCase): + + def setUp(self): + self.name_id_policy = samlp.NameIDPolicy() + + def testAccessors(self): + """Test for NameIDPolicy accessors""" + self.name_id_policy.format = saml.NAMEID_FORMAT_EMAILADDRESS + self.name_id_policy.sp_name_qualifier = saml.NAMEID_FORMAT_PERSISTENT + self.name_id_policy.allow_create = 'false' + + new_name_id_policy = samlp.NameIDPolicyFromString( + self.name_id_policy.ToString()) + + self.assert_(new_name_id_policy.format == saml.NAMEID_FORMAT_EMAILADDRESS) + self.assert_(new_name_id_policy.sp_name_qualifier == + saml.NAMEID_FORMAT_PERSISTENT) + self.assert_(new_name_id_policy.allow_create == 'false') + + def testUsingTestData(self): + """Test for NameIDPolicyFromString() using test data""" + new_name_id_policy = samlp.NameIDPolicyFromString( + samlp_test_data.TEST_NAME_ID_POLICY) + + self.assert_(new_name_id_policy.format == saml.NAMEID_FORMAT_EMAILADDRESS) + self.assert_(new_name_id_policy.sp_name_qualifier == + saml.NAMEID_FORMAT_PERSISTENT) + self.assert_(new_name_id_policy.allow_create == 'false') + + +class IDPEntryTest(unittest.TestCase): + + def setUp(self): + self.idp_entry = samlp.IDPEntry() + + def testAccessors(self): + """Test for IDPEntry accessors""" + self.idp_entry.provider_id = "http://www.sios.com/provider" + self.idp_entry.name = "the provider" + self.idp_entry.loc = "http://www.sios.com/Loc" + + new_idp_entry = samlp.IDPEntryFromString(self.idp_entry.ToString()) + self.assert_(new_idp_entry.provider_id == "http://www.sios.com/provider") + self.assert_(new_idp_entry.name == "the provider") + self.assert_(new_idp_entry.loc == "http://www.sios.com/Loc") + + def testUsingTestData(self): + """Test for IDPEntryFromString() using test data""" + new_idp_entry = samlp.IDPEntryFromString(samlp_test_data.TEST_IDP_ENTRY) + self.assert_(new_idp_entry.provider_id == "http://www.sios.com/provider") + self.assert_(new_idp_entry.name == "the provider") + self.assert_(new_idp_entry.loc == "http://www.sios.com/Loc") + + +class IDPListTest(unittest.TestCase): + + def setUp(self): + self.idp_list = samlp.IDPList() + + def testAccessors(self): + """Test for IDPList accessors""" + self.idp_list.idp_entry.append(samlp.IDPEntryFromString( + samlp_test_data.TEST_IDP_ENTRY)) + self.idp_list.get_complete = samlp.GetComplete( + text="http://www.sios.com/GetComplete") + new_idp_list = samlp.IDPListFromString(self.idp_list.ToString()) + self.assert_(isinstance(new_idp_list.idp_entry[0], samlp.IDPEntry)) + self.assert_(new_idp_list.get_complete.text.strip() == + "http://www.sios.com/GetComplete") + + def testUsingTestData(self): + """Test for IDPListFromString() using test data""" + new_idp_list = samlp.IDPListFromString(samlp_test_data.TEST_IDP_LIST) + self.assert_(isinstance(new_idp_list.idp_entry[0], samlp.IDPEntry)) + self.assert_(new_idp_list.get_complete.text.strip() == + "http://www.sios.com/GetComplete") + + +class ScopingTest(unittest.TestCase): + + def setUp(self): + self.scoping = samlp.Scoping() + + def testAccessors(self): + """Test for Scoping accessors""" + + self.scoping.proxy_count = "1" + self.scoping.idp_list = samlp.IDPList() + self.scoping.requester_id.append(samlp.RequesterID()) + + new_scoping = samlp.ScopingFromString(self.scoping.ToString()) + + self.assert_(new_scoping.proxy_count == "1") + self.assert_(isinstance(new_scoping.idp_list, samlp.IDPList)) + self.assert_(isinstance(new_scoping.requester_id[0], samlp.RequesterID)) + + def testUsingTestData(self): + """Test for ScopingFromString() using test data""" + new_scoping = samlp.ScopingFromString(samlp_test_data.TEST_SCOPING) + + self.assert_(new_scoping.proxy_count == "1") + self.assert_(isinstance(new_scoping.idp_list, samlp.IDPList)) + self.assert_(isinstance(new_scoping.requester_id[0], samlp.RequesterID)) + + +class RequestedAuthnContextTest(unittest.TestCase): + + def setUp(self): + self.context = samlp.RequestedAuthnContext() + + def testAccessors(self): + """Test for RequestedAuthnContext accessors""" + + self.context.authn_context_class_ref.append(saml.AuthnContextClassRef()) + self.context.authn_context_decl_ref.append(saml.AuthnContextDeclRef()) + self.context.comparison = "exact" + + new_context = samlp.RequestedAuthnContextFromString( + self.context.ToString()) + + self.assert_(isinstance(new_context.authn_context_class_ref[0], + saml.AuthnContextClassRef)) + self.assert_(isinstance(new_context.authn_context_decl_ref[0], + saml.AuthnContextDeclRef)) + self.assert_(new_context.comparison == "exact") + + def testUsingTestData(self): + """Test for RequestedAuthnContextFromString() using test data""" + new_context = samlp.RequestedAuthnContextFromString( + samlp_test_data.TEST_REQUESTED_AUTHN_CONTEXT) + + self.assert_(isinstance(new_context.authn_context_class_ref[0], + saml.AuthnContextClassRef)) + self.assert_(isinstance(new_context.authn_context_decl_ref[0], + saml.AuthnContextDeclRef)) + self.assert_(new_context.comparison == "exact") + + +class AuthnRequestTest(unittest.TestCase): + + def setUp(self): + self.ar = samlp.AuthnRequest() + + def testAccessors(self): + """Test for AuthnRequest accessors""" + self.ar.id = "request id" + self.ar.version = saml.V2 + self.ar.issue_instant = "2007-09-14T01:05:02Z" + self.ar.destination = "http://www.sios.com/Destination" + self.ar.consent = saml.CONSENT_UNSPECIFIED + self.ar.issuer = saml.Issuer() + self.ar.signature = ds.GetEmptySignature() + self.ar.extensions = samlp.Extensions() + + self.ar.subject = saml.Subject() + self.ar.name_id_policy = samlp.NameIDPolicy() + self.ar.conditions = saml.Conditions() + self.ar.requested_authn_context = samlp.RequestedAuthnContext() + self.ar.scoping = samlp.Scoping() + self.ar.force_authn = 'true' + self.ar.is_passive = 'true' + self.ar.assertion_consumer_service_index = "1" + self.ar.assertion_consumer_service_url = "http://www.sios.com/acs" + self.ar.protocol_binding = saml2.BINDING_HTTP_POST + self.ar.assertion_consuming_service_index = "2" + self.ar.provider_name = "provider name" + + new_ar = samlp.AuthnRequestFromString(self.ar.ToString()) + self.assert_(new_ar.id == "request id") + self.assert_(new_ar.version == saml.V2) + self.assert_(new_ar.issue_instant == "2007-09-14T01:05:02Z") + self.assert_(new_ar.destination == "http://www.sios.com/Destination") + self.assert_(new_ar.consent == saml.CONSENT_UNSPECIFIED) + self.assert_(isinstance(new_ar.issuer, saml.Issuer)) + self.assert_(isinstance(new_ar.signature, ds.Signature)) + self.assert_(isinstance(new_ar.extensions, samlp.Extensions)) + + self.assert_(isinstance(new_ar.subject, saml.Subject)) + self.assert_(isinstance(new_ar.name_id_policy, samlp.NameIDPolicy)) + self.assert_(isinstance(new_ar.conditions, saml.Conditions)) + self.assert_(isinstance(new_ar.requested_authn_context, + samlp.RequestedAuthnContext)) + self.assert_(isinstance(new_ar.scoping, samlp.Scoping)) + self.assert_(new_ar.force_authn == 'true') + self.assert_(new_ar.is_passive == 'true') + self.assert_(new_ar.assertion_consumer_service_index == '1') + self.assert_(new_ar.assertion_consumer_service_url == + 'http://www.sios.com/acs') + self.assert_(new_ar.protocol_binding == saml2.BINDING_HTTP_POST) + self.assert_(new_ar.assertion_consuming_service_index == '2') + self.assert_(new_ar.provider_name == "provider name") + + def testUsingTestData(self): + """Test for AuthnRequestFromString() using test data""" + new_ar = samlp.AuthnRequestFromString(samlp_test_data.TEST_AUTHN_REQUEST) + self.assert_(new_ar.id == "request id") + self.assert_(new_ar.version == saml.V2) + self.assert_(new_ar.issue_instant == "2007-09-14T01:05:02Z") + self.assert_(new_ar.destination == "http://www.sios.com/Destination") + self.assert_(new_ar.consent == saml.CONSENT_UNSPECIFIED) + self.assert_(isinstance(new_ar.issuer, saml.Issuer)) + self.assert_(isinstance(new_ar.signature, ds.Signature)) + self.assert_(isinstance(new_ar.extensions, samlp.Extensions)) + + self.assert_(isinstance(new_ar.subject, saml.Subject)) + self.assert_(isinstance(new_ar.name_id_policy, samlp.NameIDPolicy)) + self.assert_(isinstance(new_ar.conditions, saml.Conditions)) + self.assert_(isinstance(new_ar.requested_authn_context, + samlp.RequestedAuthnContext)) + self.assert_(isinstance(new_ar.scoping, samlp.Scoping)) + self.assert_(new_ar.force_authn == 'true') + self.assert_(new_ar.is_passive == 'true') + self.assert_(new_ar.assertion_consumer_service_index == '1') + self.assert_(new_ar.assertion_consumer_service_url == + 'http://www.sios.com/acs') + self.assert_(new_ar.protocol_binding == saml2.BINDING_HTTP_POST) + self.assert_(new_ar.assertion_consuming_service_index == '2') + self.assert_(new_ar.provider_name == "provider name") + + +class LogoutRequestTest(unittest.TestCase): + + def setUp(self): + self.lr = samlp.LogoutRequest() + + def testAccessors(self): + """Test for LogoutRequest accessors""" + self.lr.id = "request id" + self.lr.version = saml.V2 + self.lr.issue_instant = "2007-09-14T01:05:02Z" + self.lr.destination = "http://www.sios.com/Destination" + self.lr.consent = saml.CONSENT_UNSPECIFIED + self.lr.issuer = saml.Issuer() + self.lr.signature = ds.GetEmptySignature() + self.lr.extensions = samlp.Extensions() + + self.lr.not_on_or_after = "2007-10-14T01:05:02Z" + self.lr.reason = "http://www.sios.com/Reason" + self.lr.base_id = saml.BaseID() + self.lr.name_id = saml.NameID() + self.lr.encrypted_id = saml.EncryptedID() + self.lr.session_index = samlp.SessionIndex() + + new_lr = samlp.LogoutRequestFromString(self.lr.ToString()) + self.assert_(new_lr.id == "request id") + self.assert_(new_lr.version == saml.V2) + self.assert_(new_lr.issue_instant == "2007-09-14T01:05:02Z") + self.assert_(new_lr.destination == "http://www.sios.com/Destination") + self.assert_(new_lr.consent == saml.CONSENT_UNSPECIFIED) + self.assert_(isinstance(new_lr.issuer, saml.Issuer)) + self.assert_(isinstance(new_lr.signature, ds.Signature)) + self.assert_(isinstance(new_lr.extensions, samlp.Extensions)) + self.assert_(new_lr.not_on_or_after == "2007-10-14T01:05:02Z") + self.assert_(new_lr.reason == "http://www.sios.com/Reason") + self.assert_(isinstance(new_lr.base_id, saml.BaseID)) + self.assert_(isinstance(new_lr.name_id, saml.NameID)) + self.assert_(isinstance(new_lr.encrypted_id, saml.EncryptedID)) + self.assert_(isinstance(new_lr.session_index, samlp.SessionIndex)) + + def testUsingTestData(self): + """Test for LogoutRequestFromString() using test data""" + new_lr = samlp.LogoutRequestFromString(samlp_test_data.TEST_LOGOUT_REQUEST) + self.assert_(new_lr.id == "request id") + self.assert_(new_lr.version == saml.V2) + self.assert_(new_lr.issue_instant == "2007-09-14T01:05:02Z") + self.assert_(new_lr.destination == "http://www.sios.com/Destination") + self.assert_(new_lr.consent == saml.CONSENT_UNSPECIFIED) + self.assert_(isinstance(new_lr.issuer, saml.Issuer)) + self.assert_(isinstance(new_lr.signature, ds.Signature)) + self.assert_(isinstance(new_lr.extensions, samlp.Extensions)) + self.assert_(new_lr.not_on_or_after == "2007-10-14T01:05:02Z") + self.assert_(new_lr.reason == "http://www.sios.com/Reason") + self.assert_(isinstance(new_lr.base_id, saml.BaseID)) + self.assert_(isinstance(new_lr.name_id, saml.NameID)) + self.assert_(isinstance(new_lr.encrypted_id, saml.EncryptedID)) + self.assert_(isinstance(new_lr.session_index, samlp.SessionIndex)) + self.assert_(new_lr.session_index.text.strip() == "session index") + + +class LogoutResponseTest(unittest.TestCase): + + def setUp(self): + self.lr = samlp.LogoutResponse() + + def testAccessors(self): + """Test for LogoutResponse accessors""" + self.lr.id = "response id" + self.lr.in_response_to = "request id" + self.lr.version = saml.V2 + self.lr.issue_instant = "2007-09-14T01:05:02Z" + self.lr.destination = "http://www.sios.com/Destination" + self.lr.consent = saml.CONSENT_UNSPECIFIED + self.lr.issuer = saml.Issuer() + self.lr.signature = ds.GetEmptySignature() + self.lr.extensions = samlp.Extensions() + self.lr.status = samlp.Status() + + new_lr = samlp.LogoutResponseFromString(self.lr.ToString()) + self.assert_(new_lr.id == "response id") + self.assert_(new_lr.in_response_to == "request id") + self.assert_(new_lr.version == saml.V2) + self.assert_(new_lr.issue_instant == "2007-09-14T01:05:02Z") + self.assert_(new_lr.destination == "http://www.sios.com/Destination") + self.assert_(new_lr.consent == saml.CONSENT_UNSPECIFIED) + self.assert_(isinstance(new_lr.issuer, saml.Issuer)) + self.assert_(isinstance(new_lr.signature, ds.Signature)) + self.assert_(isinstance(new_lr.extensions, samlp.Extensions)) + self.assert_(isinstance(new_lr.status, samlp.Status)) + + def testUsingTestData(self): + """Test for LogoutResponseFromString() using test data""" + new_lr = samlp.LogoutResponseFromString( + samlp_test_data.TEST_LOGOUT_RESPONSE) + self.assert_(new_lr.id == "response id") + self.assert_(new_lr.in_response_to == "request id") + self.assert_(new_lr.version == saml.V2) + self.assert_(new_lr.issue_instant == "2007-09-14T01:05:02Z") + self.assert_(new_lr.destination == "http://www.sios.com/Destination") + self.assert_(new_lr.consent == saml.CONSENT_UNSPECIFIED) + self.assert_(isinstance(new_lr.issuer, saml.Issuer)) + self.assert_(isinstance(new_lr.signature, ds.Signature)) + self.assert_(isinstance(new_lr.extensions, samlp.Extensions)) + self.assert_(isinstance(new_lr.status, samlp.Status)) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_b64.py b/tests/test_b64.py new file mode 100644 index 0000000..626299d --- /dev/null +++ b/tests/test_b64.py @@ -0,0 +1,62 @@ +import base64 +import saml2 +from saml2 import samlp, saml +import urllib +import zlib + +SERVICE_URL = "http://lingon.catalogix.se/cgi-bin/repo" +MY_NAME = "My Test SP" + +SSO_LOCATION = \ + "http://xenosmilus.umdc.umu.se/simplesaml/saml2/idp/SSOService.php" + +def create_authn_request(query_id, destination, position=SERVICE_URL, provider=MY_NAME): + """ Creates an Authenication Request + + :param query_id: Query identifier + :param destination: Where to send the request + :param position: Where the user should be sent afterwards + :param provider: Who I am + + :return: A string representation of the authentication request + """ + authn_request = samlp.AuthnRequest(query_id) + authn_request.assertion_consumer_service_url = position + authn_request.destination = destination + authn_request.protocol_binding = saml2.BINDING_HTTP_POST + authn_request.provider_name = provider + + name_id_policy = samlp.NameIDPolicy() + name_id_policy.format = saml.NAMEID_FORMAT_EMAILADDRESS + name_id_policy.sp_name_qualifier = saml.NAMEID_FORMAT_PERSISTENT + name_id_policy.allow_create = 'false' + + authn_request.name_id_policy = name_id_policy + + return "%s" % authn_request + + +authn_req = create_authn_request("0123456789",SSO_LOCATION) + +b64 = base64.b64encode(authn_req) + +print base64.b64decode(b64) + +sr = """ +""" + +for i in range(1,9): + fb = urllib.quote_plus(base64.b64encode(zlib.compress(sr,i))) + print + print zlib.decompress(base64.b64decode(urllib.unquote_plus(fb))) + +one = """fZHBbtswDIbvA%2FYOgi45xc56GoQ4RdagaIF29Wr3AVSZtulIlCbKWfr2k9Nihx164YH4%2F4%2Fkz%2B312VlxgsjoqVp9KzYrAWR8hzRUq5f2dv19db37%2BmVLvFH7OY30DL9n4CT2zBBTdt144tlBbCCe0MDL80Mlx5SCKkubKZ4Ko5O2fsBzwVCaAdevSGWE4KU4ZBSSXjj%2FXGcgzw7tzMXsOpPLvBgZXbDA2tlyKVcldqFsmqePuUUYgxT3h0r6weqBDAR3PNoAkx3dcewC9p7Gqe8HchN2dpqkqKNP3nj7A%2BlysJwjKa8ZWZF2wCoZ1ewfH9RVsVGv7yJWd21br%2Bunpr0ATthB%2FJnVlXx8E%2B0STVNLkWOlTOHN59DwsYHcXRJeOPeH2ls0b2Jvrf9zE0GnzO61ZZAZvUh%2BzdpijxA%2Fhy8d7Na9j04nFZYncwJKUpS7bfn%2FR3d%2FAQ%3D%3D""" + +print zlib.decompress(base64.b64decode(urllib.unquote_plus(one)), -15) +# d1 = base64.b64decode(d0) +# print zlib.decompress(d1) + +zl = zlib.compress(sr) +# This is supposed to be safe +zl = zl[2:-4] +print urllib.quote_plus(base64.b64encode(zl)) \ No newline at end of file diff --git a/tests/test_from_string.py b/tests/test_from_string.py new file mode 100644 index 0000000..c8908ec --- /dev/null +++ b/tests/test_from_string.py @@ -0,0 +1,193 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for saml2.saml""" + +__author__ = 'roland.hedberg@adm.umu.se' + +try: + from xml.etree import ElementTree +except ImportError: + from elementtree import ElementTree +from saml2 import md +import xmldsig as ds + +X509DATA = """ + + MIICgTCCAeoCCQCbOlrWDdX7FTANBg +""" + +KEY_INFO = """ + + + MIICgTCCAeoCCQCbOlrWDdX7FTANBg + +""" + +KEY_DESCRIPTOR = """ + + + + MIICgTCCAeoCCQCbOlrWDdX7FTANBg + + +""" + +IDP = """ +""" + +ED = """ + + + + + + MIICgTCCAeoCCQCbOlrWDdX7 + + + + + + + MIICgTCCAeoCCQCbOlrWDdX7 + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + Roland + Hedberg + roland.hedberg@adm.umu.se + +""" + +ED2 = """ + + + + + + MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo + + + + + + + MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + Roland + Hedberg + roland.hedberg@adm.umu.se + +""" + +def _verify_x509data(x509data): + assert x509data.x509_certificate != [] + assert len(x509data.x509_certificate) == 1 + cert = x509data.x509_certificate[0] + assert cert.text == "MIICgTCCAeoCCQCbOlrWDdX7FTANBg" + +def test_x509data(): + x509data = ds.x509_data_from_string(X509DATA) + _verify_x509data(x509data) + +def _verify_info(info): + assert info.x509_data != [] + assert len(info.x509_data) == 1 + x509data = info.x509_data[0] + _verify_x509data(x509data) + +def test_key_info(): + info = ds.key_info_from_string(KEY_INFO) + _verify_info(info) + + +def test_key_descriptor(): + desc = md.key_descriptor_from_string(KEY_DESCRIPTOR) + assert desc.use == "signing" + print desc.__dict__ + assert desc.key_info != None + info = desc.key_info + _verify_info(info) + +def _verify_contact_person(person): + assert person.contact_type == "technical" + assert person.given_name.text == "Roland" + assert person.sur_name.text == "Hedberg" + assert person.email_address[0].text == "roland.hedberg@adm.umu.se" + +def _verify_single_sign_on_service(sso): + assert sso.binding == "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + assert sso.location == "http://xenosmilus.umdc.umu.se/simplesaml/saml2/idp/SSOService.php" + +def _verify_single_logout_service(sso): + assert sso.binding == "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + assert sso.location == "http://xenosmilus.umdc.umu.se/simplesaml/saml2/idp/SingleLogoutService.php" + +def _verify_idp_sso_description(idpssodesc): + for ssoserv in idpssodesc.single_sign_on_service: # only one + _verify_single_sign_on_service(ssoserv) + for sloserv in idpssodesc.single_logout_service: # only one + _verify_single_logout_service(sloserv) + assert idpssodesc.name_id_format[0].text == "urn:oasis:names:tc:SAML:2.0:nameid-format:transient" + +def test_entity_descriptor(): + ed = md.entity_descriptor_from_string(ED) + assert ed.entity_id == "http://xenosmilus.umdc.umu.se/simplesaml/saml2/idp/metadata.php" + contact_person = ed.contact_person[0] + _verify_contact_person(contact_person) + idpsso = ed.idp_sso_descriptor[0] + _verify_idp_sso_description(idpsso) + assert ed.entity_id == "http://xenosmilus.umdc.umu.se/simplesaml/saml2/idp/metadata.php" + print ed.to_string() + # all other attributes are supposed to be None,'',[] or {} + for key,val in ed.__dict__.items(): + if key in ["contact_person", "idp_sso_descriptor", "entity_id"]: + continue + else: + if isinstance(val,basestring): + val = val.strip('\t\r\n ') + assert val in [None,'',[],{}] + +def test_entity_descriptor_2(): + ed = md.entity_descriptor_from_string(ED2) + assert ed.entity_id == "http://xenosmilus.umdc.umu.se/simplesaml/saml2/idp/metadata.php" + contact_person = ed.contact_person[0] + _verify_contact_person(contact_person) + idpsso = ed.idp_sso_descriptor[0] + _verify_idp_sso_description(idpsso) + assert ed.entity_id == "http://xenosmilus.umdc.umu.se/simplesaml/saml2/idp/metadata.php" + print ed.to_string() + # all other attributes are supposed to be None,'',[] or {} + for key,val in ed.__dict__.items(): + if key in ["contact_person", "idp_sso_descriptor", "entity_id"]: + continue + else: + if isinstance(val,basestring): + val = val.strip('\t\r\n ') + assert val in [None,'',[],{}] + diff --git a/tests/test_md.py b/tests/test_md.py new file mode 100644 index 0000000..54baf42 --- /dev/null +++ b/tests/test_md.py @@ -0,0 +1,1152 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for saml2.md""" + +__author__ = 'tmatsuo@sios.com (Takashi MATSUO)' + +import unittest +try: + from xml.etree import ElementTree +except ImportError: + from elementtree import ElementTree +import saml2 +from saml2 import saml, samlp, md, md_test_data, ds_test_data +import xmldsig as ds + +class TestEndpoint: + + def setup_class(self): + self.endpoint = md.Endpoint() + + def testAccessors(self): + """Test for Endpoint accessors""" + self.endpoint.binding = saml2.BINDING_HTTP_POST + self.endpoint.location = "http://www.example.com/endpoint" + self.endpoint.response_location = "http://www.example.com/response" + new_endpoint = md.endpoint_from_string(self.endpoint.to_string()) + assert new_endpoint.binding == saml2.BINDING_HTTP_POST + assert new_endpoint.location == "http://www.example.com/endpoint" + assert new_endpoint.response_location == "http://www.example.com/response" + + def testUsingTestData(self): + """Test for endpoint_from_string() using test data.""" + new_endpoint = md.endpoint_from_string(md_test_data.TEST_ENDPOINT) + assert new_endpoint.binding == saml2.BINDING_HTTP_POST + assert new_endpoint.location == "http://www.example.com/endpoint" + assert new_endpoint.response_location == "http://www.example.com/response" + + +class TestIndexedEndpoint: + + def setup_class(self): + self.i_e = md.IndexedEndpoint() + + def testAccessors(self): + """Test for IndexedEndpoint accessors""" + self.i_e.binding = saml2.BINDING_HTTP_POST + self.i_e.location = "http://www.example.com/endpoint" + self.i_e.response_location = "http://www.example.com/response" + self.i_e.index = "1" + self.i_e.is_default = "false" + new_i_e = md.indexed_endpoint_from_string(self.i_e.to_string()) + assert new_i_e.binding == saml2.BINDING_HTTP_POST + assert new_i_e.location == "http://www.example.com/endpoint" + assert new_i_e.response_location == "http://www.example.com/response" + assert new_i_e.index == "1" + assert new_i_e.is_default == "false" + + def testUsingTestData(self): + """Test for indexed_endpoint_from_string() using test data.""" + new_i_e = md.indexed_endpoint_from_string(md_test_data.TEST_INDEXED_ENDPOINT) + assert new_i_e.binding == saml2.BINDING_HTTP_POST + assert new_i_e.location == "http://www.example.com/endpoint" + assert new_i_e.response_location == "http://www.example.com/response" + assert new_i_e.index == "1" + assert new_i_e.is_default == "false" + + +class TestExtensions: + + def setup_class(self): + self.extensions = md.Extensions() + + def testAccessors(self): + """Test for Extensions accessors""" + self.extensions.extension_elements.append( + saml2.extension_element_from_string( + """ + fuga + """)) + new_extensions = md.extensions_from_string(self.extensions.to_string()) + assert new_extensions.extension_elements[0].tag == "hoge" + assert new_extensions.extension_elements[0].text.strip() == "fuga" + + +class TestOrganizationName: + + def setup_class(self): + self.organization_name = md.OrganizationName() + + def testAccessors(self): + """Test for OrganizationName accessors""" + self.organization_name.lang = "en" + self.organization_name.text = "SIOS Technology, Inc." + new_organization_name = md.organization_name_from_string( + self.organization_name.to_string()) + assert new_organization_name.lang == "en" + assert new_organization_name.text.strip() == "SIOS Technology, Inc." + + def testUsingTestData(self): + """Test for organization_name_from_string() using test data.""" + new_organization_name = md.organization_name_from_string( + md_test_data.TEST_ORGANIZATION_NAME) + assert new_organization_name.lang == "en" + assert new_organization_name.text.strip() == "SIOS Technology, Inc." + + +class TestOrganizationDisplayName: + + def setup_class(self): + self.od_name = md.OrganizationDisplayName() + + def testAccessors(self): + """Test for OrganizationDisplayName accessors""" + self.od_name.lang = "en" + self.od_name.text = "SIOS" + new_od_name = md.organization_display_name_from_string( + self.od_name.to_string()) + assert new_od_name.lang == "en" + assert new_od_name.text.strip() == "SIOS" + + def testUsingTestData(self): + """Test for organization_display_name_from_string() using test data.""" + new_od_name = md.organization_display_name_from_string( + md_test_data.TEST_ORGANIZATION_DISPLAY_NAME) + assert new_od_name.lang == "en" + assert new_od_name.text.strip() == "SIOS" + + +class TestOrganizationURL: + + def setup_class(self): + self.organization_url = md.OrganizationURL() + + def testAccessors(self): + """Test for OrganizationURL accessors""" + self.organization_url.lang = "ja" + self.organization_url.text = "http://www.sios.com/" + new_organization_url = md.organization_url_from_string( + self.organization_url.to_string()) + assert new_organization_url.lang == "ja" + assert new_organization_url.text.strip() == "http://www.sios.com/" + + def testUsingTestData(self): + """Test for organization_url_from_string() using test data.""" + new_organization_url = md.organization_url_from_string( + md_test_data.TEST_ORGANIZATION_URL) + assert new_organization_url.lang == "ja" + assert new_organization_url.text.strip() == "http://www.sios.com/" + + +class TestOrganization: + + def setup_class(self): + self.organization = md.Organization() + + def testAccessors(self): + """Test for Organization accessors""" + self.organization.extensions = md.Extensions() + self.organization.organization_name.append( + md.organization_name_from_string(md_test_data.TEST_ORGANIZATION_NAME)) + self.organization.organization_display_name.append( + md.organization_display_name_from_string( + md_test_data.TEST_ORGANIZATION_DISPLAY_NAME)) + self.organization.organization_url.append( + md.organization_url_from_string(md_test_data.TEST_ORGANIZATION_URL)) + new_organization = md.organization_from_string(self.organization.to_string()) + assert isinstance(new_organization.extensions, md.Extensions) + assert isinstance(new_organization.organization_name[0], + md.OrganizationName) + assert isinstance(new_organization.organization_display_name[0], + md.OrganizationDisplayName) + assert isinstance(new_organization.organization_url[0], + md.OrganizationURL) + assert new_organization.organization_name[0].text.strip() == "SIOS Technology, Inc." + assert new_organization.organization_name[0].lang == "en" + assert new_organization.organization_display_name[0].text.strip() == "SIOS" + assert new_organization.organization_display_name[0].lang == "en" + assert new_organization.organization_url[0].text.strip() == "http://www.sios.com/" + assert new_organization.organization_url[0].lang == "ja" + + + def testUsingTestData(self): + """Test for organization_from_string() using test data.""" + new_organization = md.organization_from_string( + md_test_data.TEST_ORGANIZATION) + assert isinstance(new_organization.extensions, md.Extensions) + assert isinstance(new_organization.organization_name[0], + md.OrganizationName) + assert isinstance(new_organization.organization_display_name[0], + md.OrganizationDisplayName) + assert isinstance(new_organization.organization_url[0], + md.OrganizationURL) + assert new_organization.organization_name[0].text.strip() == "SIOS Technology, Inc." + assert new_organization.organization_name[0].lang == "en" + assert new_organization.organization_display_name[0].text.strip() == "SIOS" + assert new_organization.organization_display_name[0].lang == "en" + assert new_organization.organization_url[0].text.strip() == "http://www.sios.com/" + assert new_organization.organization_url[0].lang == "ja" + + +class TestContactPerson: + + def setup_class(self): + self.contact_person = md.ContactPerson() + + def testAccessors(self): + """Test for ContactPerson accessors""" + self.contact_person.contact_type = "technical" + self.contact_person.extensions = md.Extensions() + self.contact_person.company = md.Company(text="SIOS Technology, Inc.") + self.contact_person.given_name = md.GivenName(text="Takashi") + self.contact_person.sur_name = md.SurName(text="Matsuo") + self.contact_person.email_address.append( + md.EmailAddress(text="tmatsuo@sios.com")) + self.contact_person.email_address.append( + md.EmailAddress(text="tmatsuo@shehas.net")) + self.contact_person.telephone_number.append( + md.TelephoneNumber(text="00-0000-0000")) + new_contact_person = md.contact_person_from_string( + self.contact_person.to_string()) + assert new_contact_person.contact_type == "technical" + assert isinstance(new_contact_person.extensions, md.Extensions) + assert new_contact_person.company.text.strip() == "SIOS Technology, Inc." + assert new_contact_person.given_name.text.strip() == "Takashi" + assert new_contact_person.sur_name.text.strip() == "Matsuo" + assert new_contact_person.email_address[0].text.strip() == "tmatsuo@sios.com" + assert new_contact_person.email_address[1].text.strip() == "tmatsuo@shehas.net" + assert new_contact_person.telephone_number[0].text.strip() == "00-0000-0000" + + def testUsingTestData(self): + """Test for contact_person_from_string() using test data.""" + new_contact_person = md.contact_person_from_string( + md_test_data.TEST_CONTACT_PERSON) + assert new_contact_person.contact_type == "technical" + assert isinstance(new_contact_person.extensions, md.Extensions) + assert new_contact_person.company.text.strip() == "SIOS Technology, Inc." + assert new_contact_person.given_name.text.strip() == "Takashi" + assert new_contact_person.sur_name.text.strip() == "Matsuo" + assert new_contact_person.email_address[0].text.strip() == "tmatsuo@sios.com" + assert new_contact_person.email_address[1].text.strip() == "tmatsuo@shehas.net" + assert new_contact_person.telephone_number[0].text.strip() == "00-0000-0000" + +class TestAdditionalMetadataLocation: + + def setup_class(self): + self.additional_metadata_location = md.AdditionalMetadataLocation() + + def testAccessors(self): + """Test for AdditionalMetadataLocation accessors""" + self.additional_metadata_location.namespace = ( + "http://www.sios.com/namespace") + self.additional_metadata_location.text = ( + "http://www.sios.com/AdditionalMetadataLocation") + new_additional_metadata_location = md.additional_metadata_location_from_string( + self.additional_metadata_location.to_string()) + assert new_additional_metadata_location.namespace == "http://www.sios.com/namespace" + assert new_additional_metadata_location.text.strip() == "http://www.sios.com/AdditionalMetadataLocation" + + def testUsingTestData(self): + """Test for additional_metadata_location_from_string() using test data.""" + new_additional_metadata_location = md.additional_metadata_location_from_string( + md_test_data.TEST_ADDITIONAL_METADATA_LOCATION) + assert new_additional_metadata_location.namespace == "http://www.sios.com/namespace" + assert new_additional_metadata_location.text.strip() == "http://www.sios.com/AdditionalMetadataLocation" + +class TestKeySize: + + def setup_class(self): + self.key_size = md.KeySize() + + def testAccessors(self): + """Test for KeySize accessors""" + self.key_size.text = "128" + new_key_size = md.key_size_from_string(self.key_size.to_string()) + assert new_key_size.text.strip() == "128" + + def testUsingTestData(self): + """Test for key_size_from_string() using test data.""" + new_key_size = md.key_size_from_string(md_test_data.TEST_KEY_SIZE) + assert new_key_size.text.strip() == "128" + + +class TestOAEPparams: + + def setup_class(self): + self.oaep_params = md.OAEPparams() + + def testAccessors(self): + """Test for OAEPparams accessors""" + self.oaep_params.text = "9lWu3Q==" + new_oaep_params = md.oae_pparams_from_string(self.oaep_params.to_string()) + assert new_oaep_params.text.strip() == "9lWu3Q==" + + def testUsingTestData(self): + """Test for oae_pparams_from_string() using test data.""" + new_oaep_params = md.oae_pparams_from_string(md_test_data.TEST_OAEP_PARAMS) + assert new_oaep_params.text.strip() == "9lWu3Q==" + + +class TestEncryptionMethod: + + def setup_class(self): + self.encryption_method = md.EncryptionMethod() + + def testAccessors(self): + """Test for EncryptionMethod accessors""" + self.encryption_method.algorithm = ( + "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p") + self.encryption_method.oaep_params = md.OAEPparams(text="9lWu3Q==") + self.encryption_method.digest_method = ds.DigestMethod( + algorithm="http://www.w3.org/2000/09/xmldsig#sha1") + new_encryption_method = md.encryption_method_from_string( + self.encryption_method.to_string()) + assert new_encryption_method.algorithm == "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" + assert new_encryption_method.oaep_params.text.strip() == "9lWu3Q==" + assert new_encryption_method.digest_method.algorithm == "http://www.w3.org/2000/09/xmldsig#sha1" + + def testUsingTestData(self): + """Test for encryption_method_from_string() using test data.""" + new_encryption_method = md.encryption_method_from_string( + md_test_data.TEST_ENCRYPTION_METHOD) + assert new_encryption_method.algorithm == "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" + assert new_encryption_method.oaep_params.text.strip() == "9lWu3Q==" + assert new_encryption_method.digest_method.algorithm == "http://www.w3.org/2000/09/xmldsig#sha1" + + +class TestKeyDescriptor: + + def setup_class(self): + self.key_descriptor = md.KeyDescriptor() + + def testAccessors(self): + """Test for KeyDescriptor accessors""" + + self.key_descriptor.use = "signing" + self.key_descriptor.key_info = ds.key_info_from_string( + ds_test_data.TEST_KEY_INFO) + self.key_descriptor.encryption_method.append(md.encryption_method_from_string( + md_test_data.TEST_ENCRYPTION_METHOD)) + new_key_descriptor = md.key_descriptor_from_string( + self.key_descriptor.to_string()) + assert new_key_descriptor.use == "signing" + assert isinstance(new_key_descriptor.key_info, ds.KeyInfo) + assert isinstance(new_key_descriptor.encryption_method[0], + md.EncryptionMethod) + + def testUsingTestData(self): + """Test for key_descriptor_from_string() using test data.""" + new_key_descriptor = md.key_descriptor_from_string( + md_test_data.TEST_KEY_DESCRIPTOR) + assert new_key_descriptor.use == "signing" + assert isinstance(new_key_descriptor.key_info, ds.KeyInfo) + assert isinstance(new_key_descriptor.encryption_method[0], + md.EncryptionMethod) + + +class TestRoleDescriptor: + def setup_class(self): + self.role_descriptor = md.RoleDescriptor() + + def testAccessors(self): + """Test for RoleDescriptor accessors""" + self.role_descriptor.identifier = "ID" + self.role_descriptor.valid_until = "2008-09-14T01:05:02Z" + self.role_descriptor.cache_duration = "10:00:00:00" + self.role_descriptor.protocol_support_enumeration = samlp.SAMLP_NAMESPACE + self.role_descriptor.error_url = "http://www.sios.com/errorURL" + self.role_descriptor.signature = ds.get_empty_signature() + self.role_descriptor.extensions = md.Extensions() + self.role_descriptor.key_descriptor.append(md.key_descriptor_from_string( + md_test_data.TEST_KEY_DESCRIPTOR)) + self.role_descriptor.organization = md.Organization() + self.role_descriptor.contact_person.append(md.ContactPerson()) + + new_role_descriptor = md.role_descriptor_from_string( + self.role_descriptor.to_string()) + assert new_role_descriptor.identifier == "ID" + assert new_role_descriptor.valid_until == "2008-09-14T01:05:02Z" + assert new_role_descriptor.cache_duration == "10:00:00:00" + assert new_role_descriptor.protocol_support_enumeration == samlp.SAMLP_NAMESPACE + assert new_role_descriptor.error_url == "http://www.sios.com/errorURL" + assert isinstance(new_role_descriptor.signature, ds.Signature) + assert isinstance(new_role_descriptor.extensions, md.Extensions) + assert isinstance(new_role_descriptor.key_descriptor[0], + md.KeyDescriptor) + assert isinstance(new_role_descriptor.organization, md.Organization) + assert isinstance(new_role_descriptor.contact_person[0], + md.ContactPerson) + + def testUsingTestData(self): + """Test for role_descriptor_from_string() using test data.""" + new_role_descriptor = md.role_descriptor_from_string( + md_test_data.TEST_ROLE_DESCRIPTOR) + assert new_role_descriptor.identifier == "ID" + assert new_role_descriptor.valid_until == "2008-09-14T01:05:02Z" + assert new_role_descriptor.cache_duration == "10:00:00:00" + assert new_role_descriptor.protocol_support_enumeration == samlp.SAMLP_NAMESPACE + assert new_role_descriptor.error_url == "http://www.sios.com/errorURL" + assert isinstance(new_role_descriptor.signature, ds.Signature) + assert isinstance(new_role_descriptor.extensions, md.Extensions) + assert isinstance(new_role_descriptor.key_descriptor[0], + md.KeyDescriptor) + assert isinstance(new_role_descriptor.organization, md.Organization) + assert isinstance(new_role_descriptor.contact_person[0], + md.ContactPerson) + +class TestSSODescriptor: + def setup_class(self): + self.sso_descriptor = md.SSODescriptor() + + def testAccessors(self): + """Test for SSODescriptor accessors""" + self.sso_descriptor.identifier = "ID" + self.sso_descriptor.valid_until = "2008-09-14T01:05:02Z" + self.sso_descriptor.cache_duration = "10:00:00:00" + self.sso_descriptor.protocol_support_enumeration = samlp.SAMLP_NAMESPACE + self.sso_descriptor.error_url = "http://www.sios.com/errorURL" + self.sso_descriptor.signature = ds.get_empty_signature() + self.sso_descriptor.extensions = md.Extensions() + self.sso_descriptor.key_descriptor.append(md.key_descriptor_from_string( + md_test_data.TEST_KEY_DESCRIPTOR)) + self.sso_descriptor.organization = md.Organization() + self.sso_descriptor.contact_person.append(md.ContactPerson()) + self.sso_descriptor.artifact_resolution_service.append( + md.ArtifactResolutionService()) + self.sso_descriptor.single_logout_service.append( + md.SingleLogoutService()) + self.sso_descriptor.manage_name_id_service.append( + md.ManageNameIDService()) + self.sso_descriptor.name_id_format.append( + md.NameIDFormat()) + + new_sso_descriptor = md.sso_descriptor_from_string( + self.sso_descriptor.to_string()) + assert new_sso_descriptor.identifier == "ID" + assert new_sso_descriptor.valid_until == "2008-09-14T01:05:02Z" + assert new_sso_descriptor.cache_duration == "10:00:00:00" + assert new_sso_descriptor.protocol_support_enumeration == samlp.SAMLP_NAMESPACE + assert new_sso_descriptor.error_url == "http://www.sios.com/errorURL" + assert isinstance(new_sso_descriptor.signature, ds.Signature) + assert isinstance(new_sso_descriptor.extensions, md.Extensions) + assert isinstance(new_sso_descriptor.key_descriptor[0], + md.KeyDescriptor) + assert isinstance(new_sso_descriptor.organization, md.Organization) + assert isinstance(new_sso_descriptor.contact_person[0], + md.ContactPerson) + assert isinstance(new_sso_descriptor.artifact_resolution_service[0], + md.ArtifactResolutionService) + assert isinstance(new_sso_descriptor.single_logout_service[0], + md.SingleLogoutService) + assert isinstance(new_sso_descriptor.manage_name_id_service[0], + md.ManageNameIDService) + assert isinstance(new_sso_descriptor.name_id_format[0], + md.NameIDFormat) + + def testUsingTestData(self): + """Test for sso_descriptor_from_string() using test data.""" + new_sso_descriptor = md.sso_descriptor_from_string( + md_test_data.TEST_SSO_DESCRIPTOR) + assert new_sso_descriptor.identifier == "ID" + assert new_sso_descriptor.valid_until == "2008-09-14T01:05:02Z" + assert new_sso_descriptor.cache_duration == "10:00:00:00" + assert new_sso_descriptor.protocol_support_enumeration == samlp.SAMLP_NAMESPACE + assert new_sso_descriptor.error_url == "http://www.sios.com/errorURL" + assert isinstance(new_sso_descriptor.signature, ds.Signature) + assert isinstance(new_sso_descriptor.extensions, md.Extensions) + assert isinstance(new_sso_descriptor.key_descriptor[0], + md.KeyDescriptor) + assert isinstance(new_sso_descriptor.organization, md.Organization) + assert isinstance(new_sso_descriptor.contact_person[0], + md.ContactPerson) + assert isinstance(new_sso_descriptor.artifact_resolution_service[0], + md.ArtifactResolutionService) + assert isinstance(new_sso_descriptor.single_logout_service[0], + md.SingleLogoutService) + assert isinstance(new_sso_descriptor.manage_name_id_service[0], + md.ManageNameIDService) + assert isinstance(new_sso_descriptor.name_id_format[0], + md.NameIDFormat) + + +class TestArtifactResolutionService: + + def setup_class(self): + self.i_e = md.ArtifactResolutionService() + + def testAccessors(self): + """Test for ArtifactResolutionService accessors""" + self.i_e.binding = saml2.BINDING_HTTP_POST + self.i_e.location = "http://www.example.com/endpoint" + self.i_e.response_location = "http://www.example.com/response" + self.i_e.index = "1" + self.i_e.is_default = "false" + new_i_e = md.artifact_resolution_service_from_string(self.i_e.to_string()) + assert new_i_e.binding == saml2.BINDING_HTTP_POST + assert new_i_e.location == "http://www.example.com/endpoint" + assert new_i_e.response_location == "http://www.example.com/response" + assert new_i_e.index == "1" + assert new_i_e.is_default == "false" + + def testUsingTestData(self): + """Test for artifact_resolution_service_from_string() using test data.""" + new_i_e = md.artifact_resolution_service_from_string( + md_test_data.TEST_ARTIFACT_RESOLUTION_SERVICE) + assert new_i_e.binding == saml2.BINDING_HTTP_POST + assert new_i_e.location == "http://www.example.com/endpoint" + assert new_i_e.response_location == "http://www.example.com/response" + assert new_i_e.index == "1" + assert new_i_e.is_default == "false" + + +class TestSingleLogout: + + def setup_class(self): + self.endpoint = md.SingleLogoutService() + + def testAccessors(self): + """Test for SingleLogoutService accessors""" + self.endpoint.binding = saml2.BINDING_HTTP_POST + self.endpoint.location = "http://www.example.com/endpoint" + self.endpoint.response_location = "http://www.example.com/response" + new_endpoint = md.single_logout_service_from_string(self.endpoint.to_string()) + assert new_endpoint.binding == saml2.BINDING_HTTP_POST + assert new_endpoint.location == "http://www.example.com/endpoint" + assert new_endpoint.response_location == "http://www.example.com/response" + + def testUsingTestData(self): + """Test for single_logout_service_from_string() using test data.""" + new_endpoint = md.single_logout_service_from_string( + md_test_data.TEST_SINGLE_LOGOUT_SERVICE) + assert new_endpoint.binding == saml2.BINDING_HTTP_POST + assert new_endpoint.location == "http://www.example.com/endpoint" + assert new_endpoint.response_location == "http://www.example.com/response" + + +class TestManageNameIDService: + + def setup_class(self): + self.endpoint = md.ManageNameIDService() + + def testAccessors(self): + """Test for ManageNameIDService accessors""" + self.endpoint.binding = saml2.BINDING_HTTP_POST + self.endpoint.location = "http://www.example.com/endpoint" + self.endpoint.response_location = "http://www.example.com/response" + new_endpoint = md.manage_name_id_service_from_string(self.endpoint.to_string()) + assert new_endpoint.binding == saml2.BINDING_HTTP_POST + assert new_endpoint.location == "http://www.example.com/endpoint" + assert new_endpoint.response_location == "http://www.example.com/response" + + def testUsingTestData(self): + """Test for manage_name_id_service_from_string() using test data.""" + new_endpoint = md.manage_name_id_service_from_string( + md_test_data.TEST_MANAGE_NAMEID_SERVICE) + assert new_endpoint.binding == saml2.BINDING_HTTP_POST + assert new_endpoint.location == "http://www.example.com/endpoint" + assert new_endpoint.response_location == "http://www.example.com/response" + + +class TestNameIDFormat: + + def setup_class(self): + self.name_id_format = md.NameIDFormat() + + def testAccessors(self): + """Test for NameIDFormat accessors""" + self.name_id_format.text = saml.NAMEID_FORMAT_EMAILADDRESS + new_name_id_format = md.name_id_format_from_string( + self.name_id_format.to_string()) + assert new_name_id_format.text.strip() == saml.NAMEID_FORMAT_EMAILADDRESS + + def testUsingTestData(self): + """Test for name_id_format_from_string() using test data.""" + new_name_id_format = md.name_id_format_from_string( + md_test_data.TEST_NAME_ID_FORMAT) + assert new_name_id_format.text.strip() == saml.NAMEID_FORMAT_EMAILADDRESS + + +class TestSingleSignOnService: + + def setup_class(self): + self.endpoint = md.SingleSignOnService() + + def testAccessors(self): + """Test for SingelSignOnService accessors""" + self.endpoint.binding = saml2.BINDING_HTTP_POST + self.endpoint.location = "http://www.example.com/endpoint" + self.endpoint.response_location = "http://www.example.com/response" + new_endpoint = md.single_sign_on_service_from_string(self.endpoint.to_string()) + assert new_endpoint.binding == saml2.BINDING_HTTP_POST + assert new_endpoint.location == "http://www.example.com/endpoint" + assert new_endpoint.response_location == "http://www.example.com/response" + + def testUsingTestData(self): + """Test for SingelSignOn_service_from_string() using test data.""" + new_endpoint = md.single_sign_on_service_from_string( + md_test_data.TEST_SINGLE_SIGN_ON_SERVICE) + assert new_endpoint.binding == saml2.BINDING_HTTP_POST + assert new_endpoint.location == "http://www.example.com/endpoint" + assert new_endpoint.response_location == "http://www.example.com/response" + +class TestNameIDMappingService: + + def setup_class(self): + self.endpoint = md.NameIDMappingService() + + def testAccessors(self): + """Test for NameIDMappingService accessors""" + self.endpoint.binding = saml2.BINDING_HTTP_POST + self.endpoint.location = "http://www.example.com/endpoint" + self.endpoint.response_location = "http://www.example.com/response" + new_endpoint = md.name_id_mapping_service_from_string(self.endpoint.to_string()) + assert new_endpoint.binding == saml2.BINDING_HTTP_POST + assert new_endpoint.location == "http://www.example.com/endpoint" + assert new_endpoint.response_location == "http://www.example.com/response" + + def testUsingTestData(self): + """Test for name_id_mapping_service_from_string() using test data.""" + new_endpoint = md.name_id_mapping_service_from_string( + md_test_data.TEST_NAME_ID_MAPPING_SERVICE) + assert new_endpoint.binding == saml2.BINDING_HTTP_POST + assert new_endpoint.location == "http://www.example.com/endpoint" + assert new_endpoint.response_location == "http://www.example.com/response" + +class TestAssertionIDRequestService: + + def setup_class(self): + self.endpoint = md.AssertionIDRequestService() + + def testAccessors(self): + """Test for AssertionIDRequestService accessors""" + self.endpoint.binding = saml2.BINDING_HTTP_POST + self.endpoint.location = "http://www.example.com/endpoint" + self.endpoint.response_location = "http://www.example.com/response" + new_endpoint = md.assertion_id_request_service_from_string( + self.endpoint.to_string()) + assert new_endpoint.binding == saml2.BINDING_HTTP_POST + assert new_endpoint.location == "http://www.example.com/endpoint" + assert new_endpoint.response_location == "http://www.example.com/response" + + def testUsingTestData(self): + """Test for assertion_id_request_service_from_string() using test data.""" + new_endpoint = md.assertion_id_request_service_from_string( + md_test_data.TEST_ASSERTION_ID_REQUEST_SERVICE) + assert new_endpoint.binding == saml2.BINDING_HTTP_POST + assert new_endpoint.location == "http://www.example.com/endpoint" + assert new_endpoint.response_location == "http://www.example.com/response" + +class TestAttributeProfile: + + def setup_class(self): + self.attribute_profile = md.AttributeProfile() + + def testAccessors(self): + """Test for AttributeProfile accessors""" + self.attribute_profile.text = saml.PROFILE_ATTRIBUTE_BASIC + new_attribute_profile = md.attribute_profile_from_string( + self.attribute_profile.to_string()) + assert new_attribute_profile.text.strip() == saml.PROFILE_ATTRIBUTE_BASIC + + def testUsingTestData(self): + """Test for name_id_format_from_string() using test data.""" + new_attribute_profile = md.attribute_profile_from_string( + md_test_data.TEST_ATTRIBUTE_PROFILE) + assert new_attribute_profile.text.strip() == saml.PROFILE_ATTRIBUTE_BASIC + + +class TestIDPSSODescriptor: + def setup_class(self): + self.idp_sso_descriptor = md.IDPSSODescriptor() + + def testAccessors(self): + """Test for IDPSSODescriptor accessors""" + self.idp_sso_descriptor.identifier = "ID" + self.idp_sso_descriptor.valid_until = "2008-09-14T01:05:02Z" + self.idp_sso_descriptor.cache_duration = "10:00:00:00" + self.idp_sso_descriptor.protocol_support_enumeration = \ + samlp.SAMLP_NAMESPACE + self.idp_sso_descriptor.error_url = "http://www.sios.com/errorURL" + self.idp_sso_descriptor.signature = ds.get_empty_signature() + self.idp_sso_descriptor.extensions = md.Extensions() + self.idp_sso_descriptor.key_descriptor.append(md.key_descriptor_from_string( + md_test_data.TEST_KEY_DESCRIPTOR)) + self.idp_sso_descriptor.organization = md.Organization() + self.idp_sso_descriptor.contact_person.append(md.ContactPerson()) + self.idp_sso_descriptor.artifact_resolution_service.append( + md.ArtifactResolutionService()) + self.idp_sso_descriptor.single_logout_service.append( + md.SingleLogoutService()) + self.idp_sso_descriptor.manage_name_id_service.append( + md.ManageNameIDService()) + self.idp_sso_descriptor.name_id_format.append( + md.NameIDFormat()) + self.idp_sso_descriptor.want_authn_requests_signed = 'true' + self.idp_sso_descriptor.single_sign_on_service.append( + md.SingleSignOnService()) + self.idp_sso_descriptor.name_id_mapping_service.append( + md.NameIDMappingService()) + self.idp_sso_descriptor.assertion_id_request_service.append( + md.AssertionIDRequestService()) + self.idp_sso_descriptor.attribute_profile.append( + md.AttributeProfile()) + self.idp_sso_descriptor.attribute.append(saml.Attribute()) + + new_idp_sso_descriptor = md.idpsso_descriptor_from_string( + self.idp_sso_descriptor.to_string()) + assert new_idp_sso_descriptor.identifier == "ID" + assert new_idp_sso_descriptor.valid_until == "2008-09-14T01:05:02Z" + assert new_idp_sso_descriptor.cache_duration == "10:00:00:00" + assert new_idp_sso_descriptor.protocol_support_enumeration == samlp.SAMLP_NAMESPACE + assert new_idp_sso_descriptor.error_url == "http://www.sios.com/errorURL" + assert isinstance(new_idp_sso_descriptor.signature, ds.Signature) + assert isinstance(new_idp_sso_descriptor.extensions, md.Extensions) + assert isinstance(new_idp_sso_descriptor.key_descriptor[0], + md.KeyDescriptor) + assert isinstance(new_idp_sso_descriptor.organization, + md.Organization) + assert isinstance(new_idp_sso_descriptor.contact_person[0], + md.ContactPerson) + assert isinstance( + new_idp_sso_descriptor.artifact_resolution_service[0], + md.ArtifactResolutionService) + assert isinstance(new_idp_sso_descriptor.single_logout_service[0], + md.SingleLogoutService) + assert isinstance(new_idp_sso_descriptor.manage_name_id_service[0], + md.ManageNameIDService) + assert isinstance(new_idp_sso_descriptor.name_id_format[0], + md.NameIDFormat) + assert new_idp_sso_descriptor.want_authn_requests_signed == "true" + assert isinstance(new_idp_sso_descriptor.single_sign_on_service[0], + md.SingleSignOnService) + assert isinstance(new_idp_sso_descriptor.name_id_mapping_service[0], + md.NameIDMappingService) + assert isinstance( + new_idp_sso_descriptor.assertion_id_request_service[0], + md.AssertionIDRequestService) + assert isinstance(new_idp_sso_descriptor.attribute_profile[0], + md.AttributeProfile) + assert isinstance(new_idp_sso_descriptor.attribute[0], + saml.Attribute) + + def testUsingTestData(self): + """Test for idpsso_descriptor_from_string() using test data.""" + new_idp_sso_descriptor = md.idpsso_descriptor_from_string( + md_test_data.TEST_IDP_SSO_DESCRIPTOR) + assert new_idp_sso_descriptor.identifier == "ID" + assert new_idp_sso_descriptor.valid_until == "2008-09-14T01:05:02Z" + assert new_idp_sso_descriptor.cache_duration == "10:00:00:00" + assert new_idp_sso_descriptor.protocol_support_enumeration == samlp.SAMLP_NAMESPACE + assert new_idp_sso_descriptor.error_url == "http://www.sios.com/errorURL" + assert isinstance(new_idp_sso_descriptor.signature, ds.Signature) + assert isinstance(new_idp_sso_descriptor.extensions, md.Extensions) + assert isinstance(new_idp_sso_descriptor.key_descriptor[0], + md.KeyDescriptor) + assert isinstance(new_idp_sso_descriptor.organization, + md.Organization) + assert isinstance(new_idp_sso_descriptor.contact_person[0], + md.ContactPerson) + assert isinstance( + new_idp_sso_descriptor.artifact_resolution_service[0], + md.ArtifactResolutionService) + assert isinstance(new_idp_sso_descriptor.single_logout_service[0], + md.SingleLogoutService) + assert isinstance(new_idp_sso_descriptor.manage_name_id_service[0], + md.ManageNameIDService) + assert isinstance(new_idp_sso_descriptor.name_id_format[0], + md.NameIDFormat) + assert new_idp_sso_descriptor.want_authn_requests_signed == "true" + assert isinstance(new_idp_sso_descriptor.single_sign_on_service[0], + md.SingleSignOnService) + assert isinstance(new_idp_sso_descriptor.name_id_mapping_service[0], + md.NameIDMappingService) + assert isinstance( + new_idp_sso_descriptor.assertion_id_request_service[0], + md.AssertionIDRequestService) + assert isinstance(new_idp_sso_descriptor.attribute_profile[0], + md.AttributeProfile) + assert isinstance(new_idp_sso_descriptor.attribute[0], + saml.Attribute) + + +class TestAssertionConsumerService: + + def setup_class(self): + self.i_e = md.AssertionConsumerService() + + def testAccessors(self): + """Test for AssertionConsumerService accessors""" + self.i_e.binding = saml2.BINDING_HTTP_POST + self.i_e.location = "http://www.example.com/endpoint" + self.i_e.response_location = "http://www.example.com/response" + self.i_e.index = "1" + self.i_e.is_default = "false" + new_i_e = md.assertion_consumer_service_from_string(self.i_e.to_string()) + assert new_i_e.binding == saml2.BINDING_HTTP_POST + assert new_i_e.location == "http://www.example.com/endpoint" + assert new_i_e.response_location == "http://www.example.com/response" + assert new_i_e.index == "1" + assert new_i_e.is_default == "false" + + def testUsingTestData(self): + """Test for assertion_consumer_service_from_string() using test data.""" + new_i_e = md.assertion_consumer_service_from_string( + md_test_data.TEST_ASSERTION_CONSUMER_SERVICE) + assert new_i_e.binding == saml2.BINDING_HTTP_POST + assert new_i_e.location == "http://www.example.com/endpoint" + assert new_i_e.response_location == "http://www.example.com/response" + assert new_i_e.index == "1" + assert new_i_e.is_default == "false" + + +class TestRequestedAttribute: + + def setup_class(self): + self.requested_attribute = md.RequestedAttribute() + + def testAccessors(self): + """Test for RequestedAttribute accessors""" + assert isinstance(self.requested_attribute, saml.Attribute) + assert isinstance(self.requested_attribute, md.RequestedAttribute) + assert self.requested_attribute.is_required is None + self.requested_attribute.is_required = "true" + new_requested_attribute = md.requested_attribute_from_string( + self.requested_attribute.to_string()) + assert new_requested_attribute.is_required == "true" + assert isinstance(new_requested_attribute, saml.Attribute) + assert isinstance(new_requested_attribute, md.RequestedAttribute) + + def testUsingTestData(self): + """Test for requested_attribute_from_string() using test data.""" + new_requested_attribute = md.requested_attribute_from_string( + md_test_data.TEST_REQUESTED_ATTRIBUTE) + assert new_requested_attribute.is_required == "true" + assert isinstance(new_requested_attribute, saml.Attribute) + assert isinstance(new_requested_attribute, md.RequestedAttribute) + + +class TestServiceName: + + def setup_class(self): + self.service_name = md.ServiceName() + + def testAccessors(self): + """Test for ServiceName accessors""" + self.service_name.lang = "en" + self.service_name.text = "SIOS mail" + new_service_name = md.service_name_from_string(self.service_name.to_string()) + assert new_service_name.lang == "en" + assert new_service_name.text.strip() == "SIOS mail" + + def testUsingTestData(self): + """Test for organization_name_from_string() using test data.""" + new_service_name = md.service_name_from_string(md_test_data.TEST_SERVICE_NAME) + assert new_service_name.lang == "en" + assert new_service_name.text.strip() == "SIOS mail" + + +class TestServiceDescription: + + def setup_class(self): + self.service_description = md.ServiceDescription() + + def testAccessors(self): + """Test for ServiceDescription accessors""" + self.service_description.lang = "en" + self.service_description.text = "SIOS mail service" + new_service_description = md.service_description_from_string( + self.service_description.to_string()) + assert new_service_description.lang == "en" + assert new_service_description.text.strip() == "SIOS mail service" + + def testUsingTestData(self): + """Test for organization_name_from_string() using test data.""" + new_service_description = md.service_description_from_string( + md_test_data.TEST_SERVICE_DESCRIPTION) + assert new_service_description.lang == "en" + assert new_service_description.text.strip() == "SIOS mail service" + + +class TestAttributeConsumingService: + + def setup_class(self): + self.attribute_consuming_service = md.AttributeConsumingService() + + def testAccessors(self): + """Test for AttributeConsumingService accessors""" + self.attribute_consuming_service.service_name.append(md.ServiceName()) + self.attribute_consuming_service.service_description.append( + md.ServiceDescription()) + self.attribute_consuming_service.requested_attribute.append( + md.RequestedAttribute()) + self.attribute_consuming_service.index = "1" + self.attribute_consuming_service.is_default = "true" + + new_attribute_consuming_service = md.attribute_consuming_service_from_string( + self.attribute_consuming_service.to_string()) + assert new_attribute_consuming_service.index == "1" + assert new_attribute_consuming_service.is_default == "true" + assert isinstance(new_attribute_consuming_service.service_name[0], + md.ServiceName) + assert isinstance( + new_attribute_consuming_service.service_description[0], + md.ServiceDescription) + assert isinstance( + new_attribute_consuming_service.requested_attribute[0], + md.RequestedAttribute) + + def testUsingTestData(self): + """Test for attribute_consuming_service_from_string() using test data.""" + new_attribute_consuming_service = md.attribute_consuming_service_from_string( + md_test_data.TEST_ATTRIBUTE_CONSUMING_SERVICE) + assert new_attribute_consuming_service.index == "1" + assert new_attribute_consuming_service.is_default == "true" + assert isinstance(new_attribute_consuming_service.service_name[0], + md.ServiceName) + assert isinstance( + new_attribute_consuming_service.service_description[0], + md.ServiceDescription) + assert isinstance( + new_attribute_consuming_service.requested_attribute[0], + md.RequestedAttribute) + + +class TestSPSSODescriptor: + def setup_class(self): + self.sp_sso_descriptor = md.SPSSODescriptor() + + def testAccessors(self): + """Test for SPSSODescriptor accessors""" + self.sp_sso_descriptor.identifier = "ID" + self.sp_sso_descriptor.valid_until = "2008-09-14T01:05:02Z" + self.sp_sso_descriptor.cache_duration = "10:00:00:00" + self.sp_sso_descriptor.protocol_support_enumeration = \ + samlp.SAMLP_NAMESPACE + self.sp_sso_descriptor.error_url = "http://www.sios.com/errorURL" + self.sp_sso_descriptor.signature = ds.get_empty_signature() + self.sp_sso_descriptor.extensions = md.Extensions() + self.sp_sso_descriptor.key_descriptor.append(md.key_descriptor_from_string( + md_test_data.TEST_KEY_DESCRIPTOR)) + self.sp_sso_descriptor.organization = md.Organization() + self.sp_sso_descriptor.contact_person.append(md.ContactPerson()) + self.sp_sso_descriptor.artifact_resolution_service.append( + md.ArtifactResolutionService()) + self.sp_sso_descriptor.single_logout_service.append( + md.SingleLogoutService()) + self.sp_sso_descriptor.manage_name_id_service.append( + md.ManageNameIDService()) + self.sp_sso_descriptor.name_id_format.append( + md.NameIDFormat()) + self.sp_sso_descriptor.authn_requests_signed = "true" + self.sp_sso_descriptor.want_assertions_signed = "true" + self.sp_sso_descriptor.assertion_consumer_service.append( + md.AssertionConsumerService()) + self.sp_sso_descriptor.attribute_consuming_service.append( + md.AttributeConsumingService()) + + new_sp_sso_descriptor = md.spsso_descriptor_from_string( + self.sp_sso_descriptor.to_string()) + assert new_sp_sso_descriptor.identifier == "ID" + assert new_sp_sso_descriptor.valid_until == "2008-09-14T01:05:02Z" + assert new_sp_sso_descriptor.cache_duration == "10:00:00:00" + assert new_sp_sso_descriptor.protocol_support_enumeration == samlp.SAMLP_NAMESPACE + assert new_sp_sso_descriptor.error_url == "http://www.sios.com/errorURL" + assert isinstance(new_sp_sso_descriptor.signature, ds.Signature) + assert isinstance(new_sp_sso_descriptor.extensions, md.Extensions) + assert isinstance(new_sp_sso_descriptor.key_descriptor[0], + md.KeyDescriptor) + assert isinstance(new_sp_sso_descriptor.organization, + md.Organization) + assert isinstance(new_sp_sso_descriptor.contact_person[0], + md.ContactPerson) + assert isinstance( + new_sp_sso_descriptor.artifact_resolution_service[0], + md.ArtifactResolutionService) + assert isinstance(new_sp_sso_descriptor.single_logout_service[0], + md.SingleLogoutService) + assert isinstance(new_sp_sso_descriptor.manage_name_id_service[0], + md.ManageNameIDService) + assert isinstance(new_sp_sso_descriptor.name_id_format[0], + md.NameIDFormat) + assert new_sp_sso_descriptor.authn_requests_signed == "true" + assert new_sp_sso_descriptor.want_assertions_signed == "true" + assert isinstance( + new_sp_sso_descriptor.assertion_consumer_service[0], + md.AssertionConsumerService) + assert isinstance( + new_sp_sso_descriptor.attribute_consuming_service[0], + md.AttributeConsumingService) + + def testUsingTestData(self): + """Test for spsso_descriptor_from_string() using test data.""" + new_sp_sso_descriptor = md.spsso_descriptor_from_string( + md_test_data.TEST_SP_SSO_DESCRIPTOR) + assert new_sp_sso_descriptor.identifier == "ID" + assert new_sp_sso_descriptor.valid_until == "2008-09-14T01:05:02Z" + assert new_sp_sso_descriptor.cache_duration == "10:00:00:00" + assert new_sp_sso_descriptor.protocol_support_enumeration == samlp.SAMLP_NAMESPACE + assert new_sp_sso_descriptor.error_url == "http://www.sios.com/errorURL" + assert isinstance(new_sp_sso_descriptor.signature, ds.Signature) + assert isinstance(new_sp_sso_descriptor.extensions, md.Extensions) + assert isinstance(new_sp_sso_descriptor.key_descriptor[0], + md.KeyDescriptor) + assert isinstance(new_sp_sso_descriptor.organization, + md.Organization) + assert isinstance(new_sp_sso_descriptor.contact_person[0], + md.ContactPerson) + assert isinstance( + new_sp_sso_descriptor.artifact_resolution_service[0], + md.ArtifactResolutionService) + assert isinstance(new_sp_sso_descriptor.single_logout_service[0], + md.SingleLogoutService) + assert isinstance(new_sp_sso_descriptor.manage_name_id_service[0], + md.ManageNameIDService) + assert isinstance(new_sp_sso_descriptor.name_id_format[0], + md.NameIDFormat) + assert new_sp_sso_descriptor.authn_requests_signed == "true" + assert new_sp_sso_descriptor.want_assertions_signed == "true" + assert isinstance( + new_sp_sso_descriptor.assertion_consumer_service[0], + md.AssertionConsumerService) + assert isinstance( + new_sp_sso_descriptor.attribute_consuming_service[0], + md.AttributeConsumingService) + + +class TestEntityDescriptor: + def setup_class(self): + self.entity_descriptor = md.EntityDescriptor() + + def testAccessors(self): + """Test for RoleDescriptor accessors""" + self.entity_descriptor.identifier = "ID" + self.entity_descriptor.entity_id = "entityID" + self.entity_descriptor.valid_until = "2008-09-14T01:05:02Z" + self.entity_descriptor.cache_duration = "10:00:00:00" + + self.entity_descriptor.signature = ds.get_empty_signature() + self.entity_descriptor.extensions = md.Extensions() + self.entity_descriptor.role_descriptor.append(md.RoleDescriptor()) + self.entity_descriptor.idp_sso_descriptor.append(md.IDPSSODescriptor()) + self.entity_descriptor.sp_sso_descriptor.append(md.SPSSODescriptor()) + self.entity_descriptor.organization = md.Organization() + self.entity_descriptor.contact_person.append(md.ContactPerson()) + self.entity_descriptor.additional_metadata_location.append( + md.AdditionalMetadataLocation()) + + new_entity_descriptor = md.entity_descriptor_from_string( + self.entity_descriptor.to_string()) + assert new_entity_descriptor.identifier == "ID" + assert new_entity_descriptor.entity_id == "entityID" + assert new_entity_descriptor.valid_until == "2008-09-14T01:05:02Z" + assert new_entity_descriptor.cache_duration == "10:00:00:00" + assert isinstance(new_entity_descriptor.signature, ds.Signature) + assert isinstance(new_entity_descriptor.extensions, md.Extensions) + assert isinstance(new_entity_descriptor.role_descriptor[0], + md.RoleDescriptor) + assert isinstance(new_entity_descriptor.idp_sso_descriptor[0], + md.IDPSSODescriptor) + assert isinstance(new_entity_descriptor.sp_sso_descriptor[0], + md.SPSSODescriptor) + assert isinstance(new_entity_descriptor.organization, + md.Organization) + assert isinstance(new_entity_descriptor.contact_person[0], + md.ContactPerson) + assert isinstance( + new_entity_descriptor.additional_metadata_location[0], + md.AdditionalMetadataLocation) + + def testUsingTestData(self): + """Test for entity_descriptor_from_string() using test data.""" + new_entity_descriptor = md.entity_descriptor_from_string( + md_test_data.TEST_ENTITY_DESCRIPTOR) + assert new_entity_descriptor.identifier == "ID" + assert new_entity_descriptor.entity_id == "entityID" + assert new_entity_descriptor.valid_until == "2008-09-14T01:05:02Z" + assert new_entity_descriptor.cache_duration == "10:00:00:00" + assert isinstance(new_entity_descriptor.signature, ds.Signature) + assert isinstance(new_entity_descriptor.extensions, md.Extensions) + assert isinstance(new_entity_descriptor.role_descriptor[0], + md.RoleDescriptor) + assert isinstance(new_entity_descriptor.idp_sso_descriptor[0], + md.IDPSSODescriptor) + assert isinstance(new_entity_descriptor.sp_sso_descriptor[0], + md.SPSSODescriptor) + assert isinstance(new_entity_descriptor.organization, + md.Organization) + assert isinstance(new_entity_descriptor.contact_person[0], + md.ContactPerson) + assert isinstance(new_entity_descriptor.additional_metadata_location[0], + md.AdditionalMetadataLocation) + + +class TestEntitiesDescriptor: + def setup_class(self): + self.entities_descriptor = md.EntitiesDescriptor() + + def testAccessors(self): + """Test for EntitiesDescriptor accessors""" + self.entities_descriptor.identifier = "ID" + self.entities_descriptor.name = "name" + self.entities_descriptor.valid_until = "2008-09-14T01:05:02Z" + self.entities_descriptor.cache_duration = "10:00:00:00" + + self.entities_descriptor.signature = ds.get_empty_signature() + self.entities_descriptor.extensions = md.Extensions() + self.entities_descriptor.entity_descriptor.append(md.EntityDescriptor()) + self.entities_descriptor.entities_descriptor.append( + md.EntitiesDescriptor()) + + new_entities_descriptor = md.entities_descriptor_from_string( + self.entities_descriptor.to_string()) + assert new_entities_descriptor.identifier == "ID" + assert new_entities_descriptor.name == "name" + assert new_entities_descriptor.valid_until == "2008-09-14T01:05:02Z" + assert new_entities_descriptor.cache_duration == "10:00:00:00" + assert isinstance(new_entities_descriptor.signature, ds.Signature) + assert isinstance(new_entities_descriptor.extensions, md.Extensions) + assert isinstance(new_entities_descriptor.entity_descriptor[0], + md.EntityDescriptor) + assert isinstance(new_entities_descriptor.entities_descriptor[0], + md.EntitiesDescriptor) + + def testUsingTestData(self): + """Test for entities_descriptor_from_string() using test data.""" + new_entities_descriptor = md.entities_descriptor_from_string( + md_test_data.TEST_ENTITIES_DESCRIPTOR) + assert new_entities_descriptor.identifier == "ID" + assert new_entities_descriptor.name == "name" + assert new_entities_descriptor.valid_until == "2008-09-14T01:05:02Z" + assert new_entities_descriptor.cache_duration == "10:00:00:00" + assert isinstance(new_entities_descriptor.signature, ds.Signature) + assert isinstance(new_entities_descriptor.extensions, md.Extensions) + assert isinstance(new_entities_descriptor.entity_descriptor[0], + md.EntityDescriptor) + assert isinstance(new_entities_descriptor.entities_descriptor[0], + md.EntitiesDescriptor) + + diff --git a/tests/test_saml.py b/tests/test_saml.py new file mode 100644 index 0000000..bc785fd --- /dev/null +++ b/tests/test_saml.py @@ -0,0 +1,884 @@ +#!/usr/bin/python +# +# Copyright (C) 2007 SIOS Technology, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for saml2.saml""" + +try: + from xml.etree import ElementTree +except ImportError: + from elementtree import ElementTree +import saml2 +from saml2 import saml, test_data, ds_test_data +import xmldsig as ds + +class TestNameID: + + def setup_class(self): + self.name_id = saml.NameID() + + def testEmptyExtensionsList(self): + """Test if NameID has empty extensions list""" + assert isinstance(self.name_id.extension_elements, list) + assert len(self.name_id.extension_elements) == 0 + + def testFormatAttribute(self): + """Test for Format attribute accessors""" + self.name_id.format = saml.NAMEID_FORMAT_EMAILADDRESS + assert self.name_id.format == saml.NAMEID_FORMAT_EMAILADDRESS + assert len(self.name_id.extension_elements) == 0 + new_name_id = saml.NameIDFromString(self.name_id.to_string()) + assert len(new_name_id.extension_elements) == 0 + + self.name_id.extension_elements.append(saml2.ExtensionElement( + 'foo', text='bar')) + assert len(self.name_id.extension_elements) == 1 + assert self.name_id.format == saml.NAMEID_FORMAT_EMAILADDRESS + + def testNameIDText(self): + """Test text value of NameID element""" + self.name_id.text = "tmatsuo@sios.com" + assert self.name_id.text == "tmatsuo@sios.com" + + def testSPProvidedID(self): + """Test for SPProvidedID attribute accessors""" + self.name_id.sp_provided_id = "provided id" + assert self.name_id.sp_provided_id == "provided id" + + def testEmptyNameIDToAndFromStringMatch(self): + """Test NameIDFromString() with empty NameID""" + string_from_name_id = self.name_id.to_string() + new_name_id = saml.NameIDFromString(string_from_name_id) + string_from_new_name_id = new_name_id.to_string() + assert string_from_name_id == string_from_new_name_id + + def testNameIDToAndFromStringMatch(self): + """Test NameIDFromString() with data""" + self.name_id.format = saml.NAMEID_FORMAT_EMAILADDRESS + self.name_id.text = "tmatsuo@sios.com" + self.name_id.name_qualifier = "name_qualifier" + self.name_id.sp_name_qualifier = "sp_name_qualifier" + string_from_name_id = self.name_id.to_string() + new_name_id = saml.NameIDFromString(string_from_name_id) + assert new_name_id.name_qualifier == "name_qualifier" + assert new_name_id.sp_name_qualifier == "sp_name_qualifier" + string_from_new_name_id = new_name_id.to_string() + assert string_from_name_id == string_from_new_name_id + + def testExtensionAttributes(self): + """Test extension attributes""" + self.name_id.extension_attributes['hoge'] = 'fuga' + self.name_id.extension_attributes['moge'] = 'muga' + assert self.name_id.extension_attributes['hoge'] == 'fuga' + assert self.name_id.extension_attributes['moge'] == 'muga' + new_name_id = saml.NameIDFromString(self.name_id.to_string()) + assert new_name_id.extension_attributes['hoge'] == 'fuga' + assert new_name_id.extension_attributes['moge'] == 'muga' + + def testNameIDFromString(self): + """Test NameIDFromString() using test data""" + name_id = saml.NameIDFromString(test_data.TEST_NAME_ID) + assert name_id.format == saml.NAMEID_FORMAT_EMAILADDRESS + assert name_id.text.strip() == "tmatsuo@sios.com" + assert name_id.sp_provided_id == "sp provided id" + + +class TestIssuer: + + def setup_class(self): + self.issuer = saml.Issuer() + + def testIssuerToAndFromString(self): + """Test IssuerFromString()""" + self.issuer.text = "http://www.sios.com/test" + self.issuer.name_qualifier = "name_qualifier" + self.issuer.sp_name_qualifier = "sp_name_qualifier" + new_issuer = saml.IssuerFromString(self.issuer.to_string()) + assert self.issuer.text == new_issuer.text + assert self.issuer.name_qualifier == new_issuer.name_qualifier + assert self.issuer.sp_name_qualifier == new_issuer.sp_name_qualifier + assert self.issuer.extension_elements == new_issuer.extension_elements + + def testUsingTestData(self): + """Test IssuerFromString() using test data""" + issuer = saml.IssuerFromString(test_data.TEST_ISSUER) + assert issuer.text.strip() == "http://www.sios.com/test" + new_issuer = saml.IssuerFromString(issuer.to_string()) + assert issuer.text == new_issuer.text + assert issuer.extension_elements == new_issuer.extension_elements + + +class TestSubjectLocality: + + def setup_class(self): + self.subject_locality = saml.SubjectLocality() + + def testAccessors(self): + """Test for SubjectLocality accessors""" + self.subject_locality.address = "127.0.0.1" + self.subject_locality.dns_name = "localhost" + assert self.subject_locality.address == "127.0.0.1" + assert self.subject_locality.dns_name == "localhost" + new_subject_locality = saml.SubjectLocalityFromString( + self.subject_locality.to_string()) + assert new_subject_locality.address == "127.0.0.1" + assert new_subject_locality.dns_name == "localhost" + + def testUsingTestData(self): + """Test SubjectLocalityFromString() using test data""" + + subject_locality = saml.SubjectLocalityFromString( + test_data.TEST_SUBJECT_LOCALITY) + assert subject_locality.address == "127.0.0.1" + assert subject_locality.dns_name == "localhost" + + new_subject_locality = saml.SubjectLocalityFromString( + subject_locality.to_string()) + assert new_subject_locality.address == "127.0.0.1" + assert new_subject_locality.dns_name == "localhost" + assert subject_locality.to_string() == new_subject_locality.to_string() + + +class TestAuthnContextClassRef: + + def setup_class(self): + self.authn_context_class_ref = saml.AuthnContextClassRef() + text = "http://www.sios.com/authnContextClassRef" + + def testAccessors(self): + """Test for AuthnContextClassRef accessors""" + self.authn_context_class_ref.text = self.text + assert self.authn_context_class_ref.text == self.text + new_authn_context_class_ref = saml.AuthnContextClassRefFromString( + self.authn_context_class_ref.to_string()) + assert new_authn_context_class_ref.text == self.text + assert self.authn_context_class_ref.to_string() == \ + new_authn_context_class_ref.to_string() + + def testUsingTestData(self): + """Test AuthnContextClassRefFromString() using test data""" + authn_context_class_ref = saml.AuthnContextClassRefFromString( + test_data.TEST_AUTHN_CONTEXT_CLASS_REF) + assert authn_context_class_ref.text.strip() == self.text + + +class TestAuthnContextDeclRef: + + def setup_class(self): + self.authn_context_decl_ref = saml.AuthnContextDeclRef() + ref = "http://www.sios.com/authnContextDeclRef" + + def testAccessors(self): + """Test for AuthnContextDeclRef accessors""" + self.authn_context_decl_ref.text = self.ref + assert self.authn_context_decl_ref.text == self.ref + new_authn_context_decl_ref = saml.AuthnContextDeclRefFromString( + self.authn_context_decl_ref.to_string()) + assert new_authn_context_decl_ref.text == self.ref + assert self.authn_context_decl_ref.to_string() == \ + new_authn_context_decl_ref.to_string() + + def testUsingTestData(self): + """Test AuthnContextDeclRefFromString() using test data""" + authn_context_decl_ref = saml.AuthnContextDeclRefFromString( + test_data.TEST_AUTHN_CONTEXT_DECL_REF) + assert authn_context_decl_ref.text.strip() == self.ref + + +class TestAuthnContextDecl: + + def setup_class(self): + self.authn_context_decl = saml.AuthnContextDecl() + self.text = "http://www.sios.com/authnContextDecl" + + def testAccessors(self): + """Test for AuthnContextDecl accessors""" + self.authn_context_decl.text = self.text + assert self.authn_context_decl.text == self.text + new_authn_context_decl = saml.AuthnContextDeclFromString( + self.authn_context_decl.to_string()) + assert new_authn_context_decl.text == self.text + assert self.authn_context_decl.to_string() == \ + new_authn_context_decl.to_string() + + def testUsingTestData(self): + """Test AuthnContextDeclFromString() using test data""" + authn_context_decl = saml.AuthnContextDeclFromString( + test_data.TEST_AUTHN_CONTEXT_DECL) + assert authn_context_decl.text.strip() == self.text + + +class TestAuthenticatingAuthority: + + def setup_class(self): + self.authenticating_authority = saml.AuthenticatingAuthority() + self.text = "http://www.sios.com/authenticatingAuthority" + + def testAccessors(self): + """Test for AuthenticatingAuthority accessors""" + self.authenticating_authority.text = self.text + assert self.authenticating_authority.text == self.text + new_authenticating_authority = saml.AuthenticatingAuthorityFromString( + self.authenticating_authority.to_string()) + assert new_authenticating_authority.text == self.text + assert self.authenticating_authority.to_string() == \ + new_authenticating_authority.to_string() + + def testUsingTestData(self): + """Test AuthenticatingAuthorityFromString() using test data""" + authenticating_authority = saml.AuthenticatingAuthorityFromString( + test_data.TEST_AUTHENTICATING_AUTHORITY) + assert authenticating_authority.text.strip() == self.text + +class TestAuthnContext: + + def setup_class(self): + self.authn_context = saml.AuthnContext() + + def testAccessors(self): + """Test for AuthnContext accessors""" + self.authn_context.authn_context_class_ref = \ + saml.AuthnContextClassRefFromString( + test_data.TEST_AUTHN_CONTEXT_CLASS_REF) + self.authn_context.authn_context_decl_ref = \ + saml.AuthnContextDeclRefFromString( + test_data.TEST_AUTHN_CONTEXT_DECL_REF) + self.authn_context.authn_context_decl = \ + saml.AuthnContextDeclFromString( + test_data.TEST_AUTHN_CONTEXT_DECL) + self.authn_context.authenticating_authority.append( + saml.AuthenticatingAuthorityFromString( + test_data.TEST_AUTHENTICATING_AUTHORITY)) + assert self.authn_context.authn_context_class_ref.text.strip() == \ + "http://www.sios.com/authnContextClassRef" + assert self.authn_context.authn_context_decl_ref.text.strip() == \ + "http://www.sios.com/authnContextDeclRef" + assert self.authn_context.authn_context_decl.text.strip() == \ + "http://www.sios.com/authnContextDecl" + assert self.authn_context.authenticating_authority[0].text.strip() == \ + "http://www.sios.com/authenticatingAuthority" + new_authn_context = saml.AuthnContextFromString( + self.authn_context.to_string()) + assert self.authn_context.to_string() == new_authn_context.to_string() + + def testUsingTestData(self): + """Test AuthnContextFromString() using test data""" + authn_context = saml.AuthnContextFromString(test_data.TEST_AUTHN_CONTEXT) + assert authn_context.authn_context_class_ref.text.strip() == \ + saml.URN_PASSWORD + + +class TestAuthnStatement: + + def setup_class(self): + self.authn_statem = saml.AuthnStatement() + + def testAccessors(self): + """Test for AuthnStatement accessors""" + self.authn_statem.authn_instant = "2007-08-31T01:05:02Z" + self.authn_statem.session_not_on_or_after = "2007-09-14T01:05:02Z" + self.authn_statem.session_index = "sessionindex" + self.authn_statem.authn_context = saml.AuthnContext() + self.authn_statem.authn_context.authn_context_class_ref = \ + saml.AuthnContextClassRefFromString( + test_data.TEST_AUTHN_CONTEXT_CLASS_REF) + self.authn_statem.authn_context.authn_context_decl_ref = \ + saml.AuthnContextDeclRefFromString( + test_data.TEST_AUTHN_CONTEXT_DECL_REF) + self.authn_statem.authn_context.authn_context_decl = \ + saml.AuthnContextDeclFromString( + test_data.TEST_AUTHN_CONTEXT_DECL) + self.authn_statem.authn_context.authenticating_authority.append( + saml.AuthenticatingAuthorityFromString( + test_data.TEST_AUTHENTICATING_AUTHORITY)) + + new_as = saml.AuthnStatementFromString(self.authn_statem.to_string()) + assert new_as.authn_instant == "2007-08-31T01:05:02Z" + assert new_as.session_index == "sessionindex" + assert new_as.session_not_on_or_after == "2007-09-14T01:05:02Z" + assert new_as.authn_context.authn_context_class_ref.text.strip() == \ + "http://www.sios.com/authnContextClassRef" + assert new_as.authn_context.authn_context_decl_ref.text.strip() == \ + "http://www.sios.com/authnContextDeclRef" + assert new_as.authn_context.authn_context_decl.text.strip() == \ + "http://www.sios.com/authnContextDecl" + assert new_as.authn_context.authenticating_authority[0].text.strip() \ + == "http://www.sios.com/authenticatingAuthority" + assert self.authn_statem.to_string() == new_as.to_string() + + def testUsingTestData(self): + """Test AuthnStatementFromString() using test data""" + authn_statem = saml.AuthnStatementFromString(test_data.TEST_AUTHN_STATEMENT) + assert authn_statem.authn_instant == "2007-08-31T01:05:02Z" + assert authn_statem.session_not_on_or_after == "2007-09-14T01:05:02Z" + assert authn_statem.authn_context.authn_context_class_ref.text.strip() == \ + saml.URN_PASSWORD + + +class TestAttributeValue: + + def setup_class(self): + self.attribute_value = saml.AttributeValue() + self.text = "value for test attribute" + + def testAccessors(self): + """Test for AttributeValue accessors""" + + self.attribute_value.text = self.text + new_attribute_value = saml.AttributeValueFromString( + self.attribute_value.to_string()) + assert new_attribute_value.text.strip() == self.text + + def testUsingTestData(self): + """Test AttributeValueFromString() using test data""" + + attribute_value = saml.AttributeValueFromString( + test_data.TEST_ATTRIBUTE_VALUE) + assert attribute_value.text.strip() == self.text + + +class TestAttribute: + + def setup_class(self): + self.attribute = saml.Attribute() + self.text = ["value of test attribute", + "value1 of test attribute", + "value2 of test attribute"] + + def testAccessors(self): + """Test for Attribute accessors""" + self.attribute.name = "testAttribute" + self.attribute.name_format = saml.NAME_FORMAT_URI + self.attribute.friendly_name = "test attribute" + self.attribute.attribute_value.append(saml.AttributeValue()) + self.attribute.attribute_value[0].text = self.text[0] + + new_attribute = saml.AttributeFromString(self.attribute.to_string()) + assert new_attribute.name == "testAttribute" + assert new_attribute.name_format == saml.NAME_FORMAT_URI + assert new_attribute.friendly_name == "test attribute" + assert new_attribute.attribute_value[0].text.strip() == self.text[0] + + def testUsingTestData(self): + """Test AttributeFromString() using test data""" + attribute = saml.AttributeFromString(test_data.TEST_ATTRIBUTE) + assert attribute.name == "testAttribute" + assert attribute.name_format == saml.NAME_FORMAT_UNSPECIFIED + assert attribute.friendly_name == "test attribute" + assert attribute.attribute_value[0].text.strip() == self.text[1] + assert attribute.attribute_value[1].text.strip() == self.text[2] + # test again + attribute = saml.AttributeFromString(attribute.to_string()) + assert attribute.name == "testAttribute" + assert attribute.name_format == saml.NAME_FORMAT_UNSPECIFIED + assert attribute.friendly_name == "test attribute" + assert attribute.attribute_value[0].text.strip() == self.text[1] + assert attribute.attribute_value[1].text.strip() == self.text[2] + + +class TestAttributeStatement: + + def setup_class(self): + self.attr_statem = saml.AttributeStatement() + self.text = ["value of test attribute", + "value1 of test attribute", + "value2 of test attribute"] + + def testAccessors(self): + """Test for Attribute accessors""" + self.attr_statem.attribute.append(saml.Attribute()) + self.attr_statem.attribute.append(saml.Attribute()) + self.attr_statem.attribute[0].name = "testAttribute" + self.attr_statem.attribute[0].name_format = saml.NAME_FORMAT_URI + self.attr_statem.attribute[0].friendly_name = "test attribute" + self.attr_statem.attribute[0].attribute_value.append(saml.AttributeValue()) + self.attr_statem.attribute[0].attribute_value[0].text = self.text[0] + + self.attr_statem.attribute[1].name = "testAttribute2" + self.attr_statem.attribute[1].name_format = saml.NAME_FORMAT_UNSPECIFIED + self.attr_statem.attribute[1].friendly_name = self.text[2] + self.attr_statem.attribute[1].attribute_value.append(saml.AttributeValue()) + self.attr_statem.attribute[1].attribute_value[0].text = self.text[2] + + new_as = saml.AttributeStatementFromString(self.attr_statem.to_string()) + assert new_as.attribute[0].name == "testAttribute" + assert new_as.attribute[0].name_format == saml.NAME_FORMAT_URI + assert new_as.attribute[0].friendly_name == "test attribute" + assert new_as.attribute[0].attribute_value[0].text.strip() == self.text[0] + assert new_as.attribute[1].name == "testAttribute2" + assert new_as.attribute[1].name_format == saml.NAME_FORMAT_UNSPECIFIED + assert new_as.attribute[1].friendly_name == "test attribute2" + assert new_as.attribute[1].attribute_value[0].text.strip() == self.text[2] + + def testUsingTestData(self): + """Test AttributeStatementFromString() using test data""" + attr_statem = saml.AttributeStatementFromString(test_data.TEST_ATTRIBUTE_STATEMENT) + assert attr_statem.attribute[0].name == "testAttribute" + assert attr_statem.attribute[0].name_format == saml.NAME_FORMAT_UNSPECIFIED + assert attr_statem.attribute[0].friendly_name == "test attribute" + assert attr_statem.attribute[0].attribute_value[0].text.strip() == self.text[1] + assert attr_statem.attribute[0].attribute_value[1].text.strip() == self.text[2] + assert attr_statem.attribute[1].name == "http://www.sios.com/testAttribute2" + assert attr_statem.attribute[1].name_format == saml.NAME_FORMAT_URI + assert attr_statem.attribute[1].friendly_name == "test attribute2" + assert attr_statem.attribute[1].attribute_value[0].text.strip() == self.text[1] + assert attr_statem.attribute[1].attribute_value[1].text.strip() == self.text[2] + + # test again + attr_statem2 = saml.AttributeStatementFromString(attr_statem.to_string()) + assert attr_statem2.attribute[0].name == "testAttribute" + assert attr_statem2.attribute[0].name_format == saml.NAME_FORMAT_UNSPECIFIED + assert attr_statem2.attribute[0].friendly_name == "test attribute" + assert attr_statem2.attribute[0].attribute_value[0].text.strip() == self.text[1] + assert attr_statem2.attribute[0].attribute_value[1].text.strip() == self.text[2] + assert attr_statem2.attribute[1].name == "http://www.sios.com/testAttribute2" + assert attr_statem2.attribute[1].name_format == saml.NAME_FORMAT_URI + assert attr_statem2.attribute[1].friendly_name == "test attribute2" + assert attr_statem2.attribute[1].attribute_value[0].text.strip() == self.text[1] + assert attr_statem2.attribute[1].attribute_value[1].text.strip() == self.text[2] + + +class TestSubjectConfirmationData: + + def setup_class(self): + self.scd = saml.SubjectConfirmationData() + + def testAccessors(self): + """Test for SubjectConfirmationData accessors""" + + self.scd.not_before = "2007-08-31T01:05:02Z" + self.scd.not_on_or_after = "2007-09-14T01:05:02Z" + self.scd.recipient = "recipient" + self.scd.in_response_to = "responseID" + self.scd.address = "127.0.0.1" + new_scd = saml.SubjectConfirmationDataFromString(self.scd.to_string()) + assert new_scd.not_before == "2007-08-31T01:05:02Z" + assert new_scd.not_on_or_after == "2007-09-14T01:05:02Z" + assert new_scd.recipient == "recipient" + assert new_scd.in_response_to == "responseID" + assert new_scd.address == "127.0.0.1" + + def testUsingTestData(self): + """Test SubjectConfirmationDataFromString() using test data""" + + scd = saml.SubjectConfirmationDataFromString( + test_data.TEST_SUBJECT_CONFIRMATION_DATA) + assert scd.not_before == "2007-08-31T01:05:02Z" + assert scd.not_on_or_after == "2007-09-14T01:05:02Z" + assert scd.recipient == "recipient" + assert scd.in_response_to == "responseID" + assert scd.address == "127.0.0.1" + + +class TestSubjectConfirmation: + + def setup_class(self): + self.sc = saml.SubjectConfirmation() + + def testAccessors(self): + """Test for SubjectConfirmation accessors""" + self.sc.name_id = saml.NameIDFromString(test_data.TEST_NAME_ID) + self.sc.method = saml.SUBJECT_CONFIRMATION_METHOD_BEARER + self.sc.subject_confirmation_data = saml.SubjectConfirmationDataFromString( + test_data.TEST_SUBJECT_CONFIRMATION_DATA) + new_sc = saml.SubjectConfirmationFromString(self.sc.to_string()) + assert new_sc.name_id.sp_provided_id == "sp provided id" + assert new_sc.method == saml.SUBJECT_CONFIRMATION_METHOD_BEARER + assert new_sc.subject_confirmation_data.not_before == \ + "2007-08-31T01:05:02Z" + assert new_sc.subject_confirmation_data.not_on_or_after == \ + "2007-09-14T01:05:02Z" + assert new_sc.subject_confirmation_data.recipient == "recipient" + assert new_sc.subject_confirmation_data.in_response_to == "responseID" + assert new_sc.subject_confirmation_data.address == "127.0.0.1" + + def testUsingTestData(self): + """Test SubjectConfirmationFromString() using test data""" + + sc = saml.SubjectConfirmationFromString( + test_data.TEST_SUBJECT_CONFIRMATION) + assert sc.name_id.sp_provided_id == "sp provided id" + assert sc.method == saml.SUBJECT_CONFIRMATION_METHOD_BEARER + assert sc.subject_confirmation_data.not_before == "2007-08-31T01:05:02Z" + assert sc.subject_confirmation_data.not_on_or_after == "2007-09-14T01:05:02Z" + assert sc.subject_confirmation_data.recipient == "recipient" + assert sc.subject_confirmation_data.in_response_to == "responseID" + assert sc.subject_confirmation_data.address == "127.0.0.1" + + +class TestSubject: + + def setup_class(self): + self.subject = saml.Subject() + + def testAccessors(self): + """Test for Subject accessors""" + self.subject.name_id = saml.NameIDFromString(test_data.TEST_NAME_ID) + self.subject.subject_confirmation.append( + saml.SubjectConfirmationFromString( + test_data.TEST_SUBJECT_CONFIRMATION)) + new_subject = saml.SubjectFromString(self.subject.to_string()) + assert new_subject.name_id.sp_provided_id == "sp provided id" + assert new_subject.name_id.text.strip() == "tmatsuo@sios.com" + assert new_subject.name_id.format == saml.NAMEID_FORMAT_EMAILADDRESS + assert isinstance(new_subject.subject_confirmation[0], + saml.SubjectConfirmation) + + def testUsingTestData(self): + """Test for SubjectFromString() using test data.""" + + subject = saml.SubjectFromString(test_data.TEST_SUBJECT) + assert subject.name_id.sp_provided_id == "sp provided id" + assert subject.name_id.text.strip() == "tmatsuo@sios.com" + assert subject.name_id.format == saml.NAMEID_FORMAT_EMAILADDRESS + assert isinstance(subject.subject_confirmation[0], + saml.SubjectConfirmation) + + +class TestCondition: + + def setup_class(self): + self.condition = saml.Condition() + self.name = "{%s}type" % saml.XSI_NAMESPACE + + def testAccessors(self): + """Test for Condition accessors.""" + self.condition.extension_attributes[self.name] = "test" + self.condition.extension_attributes['ExtendedAttribute'] = "value" + new_condition = saml.ConditionFromString(self.condition.to_string()) + assert new_condition.extension_attributes[self.name] == "test" + assert new_condition.extension_attributes["ExtendedAttribute"] == "value" + + def testUsingTestData(self): + """Test for ConditionFromString() using test data.""" + condition = saml.ConditionFromString(test_data.TEST_CONDITION) + assert condition.extension_attributes[self.name] == "test" + assert condition.extension_attributes["ExtendedAttribute"] == "value" + + +class TestAudience: + + def setup_class(self): + self.audience = saml.Audience() + + def testAccessors(self): + """Test for Audience accessors""" + + self.audience.text = "http://www.sios.com/Audience" + new_audience = saml.AudienceFromString(self.audience.to_string()) + assert new_audience.text.strip() == "http://www.sios.com/Audience" + + def testUsingTestData(self): + """Test AudienceFromString using test data""" + + audience = saml.AudienceFromString(test_data.TEST_AUDIENCE) + assert audience.text.strip() == "http://www.sios.com/Audience" + + +class TestAudienceRestriction: + def setup_class(self): + self.audience_restriction = saml.AudienceRestriction() + + def testAccessors(self): + """Test for AudienceRestriction accessors""" + + self.audience_restriction.audience = \ + saml.AudienceFromString(test_data.TEST_AUDIENCE) + new_audience = saml.AudienceRestrictionFromString( + self.audience_restriction.to_string()) + assert self.audience_restriction.audience.text.strip() == \ + "http://www.sios.com/Audience" + + def testUsingTestData(self): + """Test AudienceRestrictionFromString using test data""" + + audience_restriction = saml.AudienceRestrictionFromString( + test_data.TEST_AUDIENCE_RESTRICTION) + assert audience_restriction.audience.text.strip() == \ + "http://www.sios.com/Audience" + + +class TestOneTimeUse: + + def setup_class(self): + self.one_time_use = saml.OneTimeUse() + + def testAccessors(self): + """Test for OneTimeUse accessors""" + assert isinstance(self.one_time_use, saml.OneTimeUse) + assert isinstance(self.one_time_use, saml.Condition) + + def testUsingTestData(self): + """Test OneTimeUseFromString() using test data""" + one_time_use = saml.OneTimeUseFromString(test_data.TEST_ONE_TIME_USE) + assert isinstance(one_time_use, saml.OneTimeUse) + assert isinstance(one_time_use, saml.Condition) + + +class TestProxyRestriction: + + def setup_class(self): + self.proxy_restriction = saml.ProxyRestriction() + + def testAccessors(self): + """Test for ProxyRestriction accessors""" + + assert isinstance(self.proxy_restriction, saml.Condition) + self.proxy_restriction.count = "2" + self.proxy_restriction.audience.append(saml.AudienceFromString( + test_data.TEST_AUDIENCE)) + new_proxy_restriction = saml.ProxyRestrictionFromString( + self.proxy_restriction.to_string()) + assert new_proxy_restriction.count == "2" + assert new_proxy_restriction.audience[0].text.strip() == \ + "http://www.sios.com/Audience" + + def testUsingTestData(self): + """Test ProxyRestrictionFromString() using test data""" + + proxy_restriction = saml.ProxyRestrictionFromString( + test_data.TEST_PROXY_RESTRICTION) + assert proxy_restriction.count == "2" + assert proxy_restriction.audience[0].text.strip() == \ + "http://www.sios.com/Audience" + +class TestConditions: + + def setup_class(self): + self.conditions = saml.Conditions() + + def testAccessors(self): + """Test for Conditions accessors""" + self.conditions.not_before = "2007-08-31T01:05:02Z" + self.conditions.not_on_or_after = "2007-09-14T01:05:02Z" + self.conditions.condition.append(saml.Condition()) + self.conditions.audience_restriction.append(saml.AudienceRestriction()) + self.conditions.one_time_use.append(saml.OneTimeUse()) + self.conditions.proxy_restriction.append(saml.ProxyRestriction()) + new_conditions = saml.ConditionsFromString(self.conditions.to_string()) + assert new_conditions.not_before == "2007-08-31T01:05:02Z" + assert new_conditions.not_on_or_after == "2007-09-14T01:05:02Z" + assert isinstance(new_conditions.condition[0], saml.Condition) + assert isinstance(new_conditions.audience_restriction[0], + saml.AudienceRestriction) + assert isinstance(new_conditions.one_time_use[0], + saml.OneTimeUse) + assert isinstance(new_conditions.proxy_restriction[0], + saml.ProxyRestriction) + + def testUsingTestData(self): + """Test ConditionsFromString() using test data""" + new_conditions = saml.ConditionsFromString(test_data.TEST_CONDITIONS) + assert new_conditions.not_before == "2007-08-31T01:05:02Z" + assert new_conditions.not_on_or_after == "2007-09-14T01:05:02Z" + assert isinstance(new_conditions.condition[0], saml.Condition) + assert isinstance(new_conditions.audience_restriction[0], + saml.AudienceRestriction) + assert isinstance(new_conditions.one_time_use[0], + saml.OneTimeUse) + assert isinstance(new_conditions.proxy_restriction[0], + saml.ProxyRestriction) + +class TestAssertionIDRef: + + def setup_class(self): + self.assertion_id_ref = saml.AssertionIDRef() + + def testAccessors(self): + """Test for AssertionIDRef accessors""" + self.assertion_id_ref.text = "zzlieajngjbkjggjldmgindkckkolcblndbghlhm" + new_assertion_id_ref = saml.AssertionIDRefFromString( + self.assertion_id_ref.to_string()) + assert new_assertion_id_ref.text == \ + "zzlieajngjbkjggjldmgindkckkolcblndbghlhm" + + def testUsingTestData(self): + """Test AssertionIDRefFromString() using test data""" + new_assertion_id_ref = saml.AssertionIDRefFromString( + test_data.TEST_ASSERTION_ID_REF) + assert new_assertion_id_ref.text.strip() == \ + "zzlieajngjbkjggjldmgindkckkolcblndbghlhm" + + +class TestAssertionURIRef: + + def setup_class(self): + self.assertion_uri_ref = saml.AssertionURIRef() + + def testAccessors(self): + """Test for AssertionURIRef accessors""" + self.assertion_uri_ref.text = "http://www.sios.com/AssertionURIRef" + new_assertion_uri_ref = saml.AssertionURIRefFromString( + self.assertion_uri_ref.to_string()) + assert new_assertion_uri_ref.text == \ + "http://www.sios.com/AssertionURIRef" + + def testUsingTestData(self): + """Test AssertionURIRefFromString() using test data""" + new_assertion_uri_ref = saml.AssertionURIRefFromString( + test_data.TEST_ASSERTION_URI_REF) + assert new_assertion_uri_ref.text.strip() == \ + "http://www.sios.com/AssertionURIRef" + + +class TestAction: + + def setup_class(self): + self.action = saml.Action() + + def testAccessors(self): + """Test for Action accessors""" + self.action.namespace = "http://www.sios.com/Namespace" + new_action = saml.ActionFromString(self.action.to_string()) + assert new_action.namespace == "http://www.sios.com/Namespace" + + def testUsingTestData(self): + """Test ActionFromString() using test data""" + new_action = saml.ActionFromString(test_data.TEST_ACTION) + assert new_action.namespace == "http://www.sios.com/Namespace" + + +class TestEvidence: + + def setup_class(self): + self.evidence = saml.Evidence() + + def testAccessors(self): + """Test for Evidence accessors""" + self.evidence.assertion_id_ref.append(saml.AssertionIDRef()) + self.evidence.assertion_uri_ref.append(saml.AssertionURIRef()) + self.evidence.assertion.append(saml.Assertion()) + self.evidence.encrypted_assertion.append(saml.EncryptedAssertion()) + new_evidence = saml.EvidenceFromString(self.evidence.to_string()) + assert self.evidence.to_string() == new_evidence.to_string() + assert isinstance(new_evidence.assertion_id_ref[0], + saml.AssertionIDRef) + assert isinstance(new_evidence.assertion_uri_ref[0], + saml.AssertionURIRef) + assert isinstance(new_evidence.assertion[0], saml.Assertion) + assert isinstance(new_evidence.encrypted_assertion[0], + saml.EncryptedAssertion) + + def testUsingTestData(self): + """Test EvidenceFromString() using test data""" + # TODO: + pass + + +class TestAuthzDecisionStatement: + + def setup_class(self): + self.authz_decision_statement = saml.AuthzDecisionStatement() + + def testAccessors(self): + """Test for AuthzDecisionStatement accessors""" + self.authz_decision_statement.resource = "http://www.sios.com/Resource" + self.authz_decision_statement.decision = saml.DECISION_TYPE_PERMIT + self.authz_decision_statement.action.append(saml.Action()) + self.authz_decision_statement.evidence.append(saml.Evidence()) + new_authz_decision_statement = saml.AuthzDecisionStatementFromString( + self.authz_decision_statement.to_string()) + assert self.authz_decision_statement.to_string() == \ + new_authz_decision_statement.to_string() + assert new_authz_decision_statement.resource == \ + "http://www.sios.com/Resource" + assert new_authz_decision_statement.decision == \ + saml.DECISION_TYPE_PERMIT + assert isinstance(new_authz_decision_statement.action[0], + saml.Action) + assert isinstance(new_authz_decision_statement.evidence[0], + saml.Evidence) + + + def testUsingTestData(self): + """Test AuthzDecisionStatementFromString() using test data""" + # TODO: + pass + +class TestAdvice: + + def setup_class(self): + self.advice = saml.Advice() + + def testAccessors(self): + """Test for Advice accessors""" + self.advice.assertion_id_ref.append(saml.AssertionIDRef()) + self.advice.assertion_uri_ref.append(saml.AssertionURIRef()) + self.advice.assertion.append(saml.Assertion()) + self.advice.encrypted_assertion.append(saml.EncryptedAssertion()) + new_advice = saml.AdviceFromString(self.advice.to_string()) + assert self.advice.to_string() == new_advice.to_string() + assert isinstance(new_advice.assertion_id_ref[0], + saml.AssertionIDRef) + assert isinstance(new_advice.assertion_uri_ref[0], + saml.AssertionURIRef) + assert isinstance(new_advice.assertion[0], saml.Assertion) + assert isinstance(new_advice.encrypted_assertion[0], + saml.EncryptedAssertion) + + def testUsingTestData(self): + """Test AdviceFromString() using test data""" + # TODO: + pass + + +class TestAssertion: + + def setup_class(self): + self.assertion = saml.Assertion() + + def testAccessors(self): + """Test for Assertion accessors""" + self.assertion.id = "assertion id" + self.assertion.version = saml.V2 + self.assertion.issue_instant = "2007-08-31T01:05:02Z" + self.assertion.issuer = saml.IssuerFromString(test_data.TEST_ISSUER) + self.assertion.signature = ds.SignatureFromString( + ds_test_data.TEST_SIGNATURE) + self.assertion.subject = saml.SubjectFromString(test_data.TEST_SUBJECT) + self.assertion.conditions = saml.ConditionsFromString( + test_data.TEST_CONDITIONS) + self.assertion.advice = saml.Advice() + self.assertion.statement.append(saml.Statement()) + self.assertion.authn_statement.append(saml.AuthnStatementFromString( + test_data.TEST_AUTHN_STATEMENT)) + self.assertion.authz_decision_statement.append( + saml.AuthzDecisionStatement()) + self.assertion.attribute_statement.append( + saml.AttributeStatementFromString( + test_data.TEST_ATTRIBUTE_STATEMENT)) + + new_assertion = saml.AssertionFromString(self.assertion.to_string()) + assert new_assertion.id == "assertion id" + assert new_assertion.version == saml.V2 + assert new_assertion.issue_instant == "2007-08-31T01:05:02Z" + assert isinstance(new_assertion.issuer, saml.Issuer) + assert isinstance(new_assertion.signature, ds.Signature) + assert isinstance(new_assertion.subject, saml.Subject) + assert isinstance(new_assertion.conditions, saml.Conditions) + assert isinstance(new_assertion.advice, saml.Advice) + assert isinstance(new_assertion.statement[0], saml.Statement) + assert isinstance(new_assertion.authn_statement[0], + saml.AuthnStatement) + assert isinstance(new_assertion.authz_decision_statement[0], + saml.AuthzDecisionStatement) + assert isinstance(new_assertion.attribute_statement[0], + saml.AttributeStatement) + + + def testUsingTestData(self): + """Test AssertionFromString() using test data""" + # TODO + pass