Skip to content

Commit

Permalink
unit test passes - ElementTree namespaces initialized globally in sam…
Browse files Browse the repository at this point in the history
…l2.__init__
  • Loading branch information
peppelinux committed Jul 20, 2019
1 parent ec9d640 commit 2be14b0
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 31 deletions.
44 changes: 33 additions & 11 deletions src/saml2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
provides methods and functions to convert SAML classes to and from strings.
"""

import copy
import logging

import six
Expand Down Expand Up @@ -58,14 +59,28 @@
DS_NAMESPACE = 'http://www.w3.org/2000/09/xmldsig#'
MD_NAMESPACE = "urn:oasis:names:tc:SAML:2.0:metadata"
MDUI_NAMESPACE = "urn:oasis:names:tc:SAML:metadata:ui"
DEFAULT_NS_PREFIXES = {'saml': NAMESPACE, 'samlp': SAMLP_NAMESPACE,
'ds': DS_NAMESPACE, 'xsi': XSI_NAMESPACE,
'xs': XS_NAMESPACE,
'mdui': MDUI_NAMESPACE,
'md': MD_NAMESPACE,
# 'alg': TODO: algsupport.DIGEST_METHODS|SIGNING_METHODS shoulb be moved before mapping them here
# TODO: <ns1:EntityAttributes>
}
XENC_NAMESPACE = "http://www.w3.org/2001/04/xmlenc#"

# this should be configurable by users
OASIS_DEFAULT_NS_PREFIXES = {'saml': NAMESPACE, 'samlp': SAMLP_NAMESPACE,
'ds': DS_NAMESPACE, 'xsi': XSI_NAMESPACE,
'xs': XS_NAMESPACE,
'mdui': MDUI_NAMESPACE,
'md': MD_NAMESPACE,
'xenc': XENC_NAMESPACE,
# mdattr: <ns1:EntityAttributes>
}


# make DEFAULT_NS_PREFIXES as default without register ns in every entities
for prefix, uri in OASIS_DEFAULT_NS_PREFIXES.items():
try:
ElementTree.register_namespace(prefix, uri)
except AttributeError:
# Backwards compatibility with ET < 1.3
ElementTree._namespace_map[uri] = prefix
except ValueError:
pass


NAMEID_FORMAT_EMAILADDRESS = (
Expand All @@ -90,6 +105,13 @@
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 replace_ns_prefixes(value, ns):
"""function to adapt ns to user's customs
"""
if not SWAPPED_NS_PREFIXES:
return value
return value.replace(DEFAULT_SWAPPED_NS_PREFIXES[ns],
SWAPPED_NS_PREFIXES[ns])

def class_name(instance):
return "%s:%s" % (instance.c_namespace, instance.c_tag)
Expand Down Expand Up @@ -705,19 +727,19 @@ def to_string_force_namespace(self, nspair):

return ElementTree.tostring(elem, encoding="UTF-8")

def to_string(self, nspair=DEFAULT_NS_PREFIXES):
def to_string(self, nspair=None):
"""Converts the Saml object to a string containing XML.
:param nspair: A dictionary of prefixes and uris to use when
constructing the text representation.
:return: String representation of the object
"""
if not nspair and self.c_ns_prefix:
if self.c_ns_prefix:
nspair = self.c_ns_prefix

if nspair:
self.register_prefix(nspair)

return ElementTree.tostring(self._to_element_tree(), encoding="UTF-8")

def __str__(self):
Expand Down
4 changes: 2 additions & 2 deletions tests/test_02_saml.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,11 +226,11 @@ def test_to_string_nspair(self):
foo = saml2.make_vals("lions", AttributeValue, part=True)
txt = foo.to_string().decode('utf-8')
nsstr = foo.to_string({"saml": saml.NAMESPACE}).decode('utf-8')
assert nsstr != txt
assert nsstr == txt # this must be the same
print(txt)
print(nsstr)
assert "saml:AttributeValue" in nsstr
assert "saml:AttributeValue" not in txt
assert "saml:AttributeValue" in txt # this must be contained

def test_set_text_empty(self):
av = AttributeValue()
Expand Down
18 changes: 9 additions & 9 deletions tests/test_12_s_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,25 @@
XML_HEADER = '<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n'

SUCCESS_STATUS_NO_HEADER = (
'<ns0:Status xmlns:ns0="urn:oasis:names:tc:SAML:2.0:protocol"><ns0'
'<samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"><samlp'
':StatusCode '
'Value="urn:oasis:names:tc:SAML:2.0:status:Success" /></ns0:Status>')
'Value="urn:oasis:names:tc:SAML:2.0:status:Success" /></samlp:Status>')
SUCCESS_STATUS = '%s%s' % (XML_HEADER, SUCCESS_STATUS_NO_HEADER)

ERROR_STATUS_NO_HEADER = (
'<ns0:Status xmlns:ns0="urn:oasis:names:tc:SAML:2.0:protocol"><ns0'
'<samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"><samlp'
':StatusCode '
'Value="urn:oasis:names:tc:SAML:2.0:status:Responder"><ns0:StatusCode '
'Value="urn:oasis:names:tc:SAML:2.0:status:Responder"><samlp:StatusCode '
'Value="urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal" '
'/></ns0:StatusCode><ns0:StatusMessage>Error resolving '
'principal</ns0:StatusMessage></ns0:Status>')
'/></samlp:StatusCode><samlp:StatusMessage>Error resolving '
'principal</samlp:StatusMessage></samlp:Status>')

ERROR_STATUS_NO_HEADER_EMPTY = (
'<ns0:Status xmlns:ns0="urn:oasis:names:tc:SAML:2.0:protocol"><ns0'
'<samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"><samlp'
':StatusCode '
'Value="urn:oasis:names:tc:SAML:2.0:status:Responder"><ns0:StatusCode '
'Value="urn:oasis:names:tc:SAML:2.0:status:Responder"><samlp:StatusCode '
'Value="urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal" '
'/></ns0:StatusCode></ns0:Status>')
'/></samlp:StatusCode></samlp:Status>')

ERROR_STATUS = '%s%s' % (XML_HEADER, ERROR_STATUS_NO_HEADER)
ERROR_STATUS_EMPTY = '%s%s' % (XML_HEADER, ERROR_STATUS_NO_HEADER_EMPTY)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_42_enc.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

__author__ = 'roland'

TMPL_NO_HEADER = """<ns0:EncryptedData xmlns:ns0="http://www.w3.org/2001/04/xmlenc#" xmlns:ns1="http://www.w3.org/2000/09/xmldsig#" Id="ED" Type="http://www.w3.org/2001/04/xmlenc#Element"><ns0:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /><ns1:KeyInfo><ns0:EncryptedKey Id="EK"><ns0:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /><ns1:KeyInfo><ns1:KeyName>my-rsa-key</ns1:KeyName></ns1:KeyInfo><ns0:CipherData><ns0:CipherValue /></ns0:CipherData></ns0:EncryptedKey></ns1:KeyInfo><ns0:CipherData><ns0:CipherValue /></ns0:CipherData></ns0:EncryptedData>"""
TMPL_NO_HEADER = """<xenc:EncryptedData xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="ED" Type="http://www.w3.org/2001/04/xmlenc#Element"><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /><ds:KeyInfo><xenc:EncryptedKey Id="EK"><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /><ds:KeyInfo><ds:KeyName>my-rsa-key</ds:KeyName></ds:KeyInfo><xenc:CipherData><xenc:CipherValue /></xenc:CipherData></xenc:EncryptedKey></ds:KeyInfo><xenc:CipherData><xenc:CipherValue /></xenc:CipherData></xenc:EncryptedData>"""
TMPL = "<?xml version='1.0' encoding='UTF-8'?>\n%s" % TMPL_NO_HEADER

IDENTITY = {"eduPersonAffiliation": ["staff", "member"],
Expand Down
8 changes: 4 additions & 4 deletions tests/test_51_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1476,7 +1476,7 @@ def test_do_logout_post(self):
_dic = unpack_form(info["data"])
res = self.server.parse_logout_request(_dic["SAMLRequest"],
BINDING_HTTP_POST)
assert b'<ns0:SessionIndex>_foo</ns0:SessionIndex>' in res.xmlstr
assert b'<samlp:SessionIndex>_foo</samlp:SessionIndex>' in res.xmlstr

def test_do_logout_session_expired(self):
# information about the user from an IdP
Expand Down Expand Up @@ -1506,7 +1506,7 @@ def test_do_logout_session_expired(self):
_dic = unpack_form(info["data"])
res = self.server.parse_logout_request(_dic["SAMLRequest"],
BINDING_HTTP_POST)
assert b'<ns0:SessionIndex>_foo</ns0:SessionIndex>' in res.xmlstr
assert b'<samlp:SessionIndex>_foo</samlp:SessionIndex>' in res.xmlstr

def test_signature_wants(self):

Expand Down Expand Up @@ -3053,7 +3053,7 @@ def test_do_logout_post(self):
_dic = unpack_form(info["data"])
res = self.server.parse_logout_request(_dic["SAMLRequest"],
BINDING_HTTP_POST)
assert b'<ns0:SessionIndex>_foo</ns0:SessionIndex>' in res.xmlstr
assert b'<samlp:SessionIndex>_foo</samlp:SessionIndex>' in res.xmlstr

def test_do_logout_session_expired(self):
# information about the user from an IdP
Expand Down Expand Up @@ -3083,7 +3083,7 @@ def test_do_logout_session_expired(self):
_dic = unpack_form(info["data"])
res = self.server.parse_logout_request(_dic["SAMLRequest"],
BINDING_HTTP_POST)
assert b'<ns0:SessionIndex>_foo</ns0:SessionIndex>' in res.xmlstr
assert b'<samlp:SessionIndex>_foo</samlp:SessionIndex>' in res.xmlstr

# Below can only be done with dummy Server
IDP = "urn:mace:example.com:saml:roland:idp"
Expand Down
14 changes: 10 additions & 4 deletions tests/test_88_nsprefix.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@ def test_nsprefix():
status_message = samlp.StatusMessage()
status_message.text = "OK"

# not possibile: ns0 -> raise ValueError("Prefix format reserved for internal use")
#status_message.register_prefix(nspair={"ns0": saml.NAMESPACE,
#"ns0": samlp.NAMESPACE})

status_message.register_prefix(nspair={"samla": saml.NAMESPACE,
"samla": samlp.NAMESPACE})
txt = "%s" % status_message

assert "ns0:StatusMessage" in txt
assert "samla:StatusMessage" in txt

status_message.register_prefix({"saml2": saml.NAMESPACE,
"saml2p": samlp.NAMESPACE})
status_message.register_prefix(nspair={"saml2p": samlp.NAMESPACE,
"saml2": saml.NAMESPACE})

txt = "%s" % status_message

Expand All @@ -42,4 +48,4 @@ def test_nsprefix2():
assert "saml2:Issuer" in txt

if __name__ == "__main__":
test_nsprefix2()
test_nsprefix2()

0 comments on commit 2be14b0

Please # to comment.