Final touch to ECP

Worked through a NameIDMapping test
This commit is contained in:
Roland Hedberg 2013-01-25 13:50:00 +01:00
parent db681c0841
commit edf1819015
7 changed files with 38 additions and 26 deletions

View File

@ -37,7 +37,7 @@ class PyTest(Command):
install_requires=[ install_requires=[
# core dependencies # core dependencies
'decorator', 'decorator',
'httplib2', 'requests >= 1.0.0',
'paste', 'paste',
'zope.interface', 'zope.interface',
'repoze.who == 1.0.18' 'repoze.who == 1.0.18'

View File

@ -18,7 +18,6 @@
"""Contains classes and functions that a SAML2.0 Service Provider (SP) may use """Contains classes and functions that a SAML2.0 Service Provider (SP) may use
to conclude its tasks. to conclude its tasks.
""" """
from saml2.schema import soapenv
from saml2.entity import Entity from saml2.entity import Entity
from saml2.mdstore import destinations from saml2.mdstore import destinations
@ -43,7 +42,7 @@ except ImportError:
from saml2.s_utils import signature from saml2.s_utils import signature
from saml2.s_utils import do_attributes from saml2.s_utils import do_attributes
from saml2 import samlp, BINDING_SOAP, element_to_extension_element from saml2 import samlp, BINDING_SOAP
from saml2 import saml from saml2 import saml
from saml2 import soap from saml2 import soap
from saml2.population import Population from saml2.population import Population
@ -468,7 +467,7 @@ class Base(Entity):
# ======== response handling =========== # ======== response handling ===========
def parse_authn_request_response(self, xmlstr, binding, outstanding): def parse_authn_request_response(self, xmlstr, binding, outstanding=None):
""" Deal with an AuthnResponse """ Deal with an AuthnResponse
:param xmlstr: The reply as a xml string :param xmlstr: The reply as a xml string
@ -564,7 +563,8 @@ class Base(Entity):
# ------------------- ECP ------------------------------------------------ # ------------------- ECP ------------------------------------------------
def create_ecp_authn_request(self, entityid=None, relay_state="", sign=False): def create_ecp_authn_request(self, entityid=None, relay_state="",
sign=False, **kwargs):
""" Makes an authentication request. """ Makes an authentication request.
:param entityid: The entity ID of the IdP to send the request to :param entityid: The entity ID of the IdP to send the request to
@ -596,14 +596,24 @@ class Base(Entity):
# <samlp:AuthnRequest> # <samlp:AuthnRequest>
# ---------------------------------------- # ----------------------------------------
logger.info("entityid: %s, binding: %s" % (entityid, BINDING_SOAP)) try:
authn_req = kwargs["authn_req"]
except KeyError:
try:
_binding = kwargs["binding"]
except KeyError:
_binding = BINDING_SOAP
kwargs["binding"] = _binding
# The IDP publishes support for ECP by using the SOAP binding on logger.debug("entityid: %s, binding: %s" % (entityid, _binding))
# SingleSignOnService
_, location = self.pick_binding("single_sign_on_service", # The IDP publishes support for ECP by using the SOAP binding on
[BINDING_SOAP], entity_id=entityid) # SingleSignOnService
authn_req = self.create_authn_request(location, binding=BINDING_SOAP, _, location = self.pick_binding("single_sign_on_service",
service_url_binding=BINDING_PAOS) [_binding], entity_id=entityid)
authn_req = self.create_authn_request(location,
service_url_binding=BINDING_PAOS,
**kwargs)
# ---------------------------------------- # ----------------------------------------
# The SOAP envelope # The SOAP envelope

View File

@ -7,7 +7,6 @@ import urlparse
import requests import requests
import time import time
from Cookie import SimpleCookie from Cookie import SimpleCookie
from saml2.profile import paos
from saml2.time_util import utc_now from saml2.time_util import utc_now
from saml2 import class_name from saml2 import class_name
from saml2.pack import http_form_post_message from saml2.pack import http_form_post_message
@ -262,7 +261,7 @@ class HTTPBase(object):
:param request: :param request:
:param destination: :param destination:
:param headers: :param soap_headers:
:param sign: :param sign:
:return: dictionary :return: dictionary
""" """
@ -270,7 +269,7 @@ class HTTPBase(object):
soap_message = make_soap_enveloped_saml_thingy(request, soap_headers) soap_message = make_soap_enveloped_saml_thingy(request, soap_headers)
logger.error("SOAP message: %s" % soap_message) logger.debug("SOAP message: %s" % soap_message)
if sign and self.sec: if sign and self.sec:
_signed = self.sec.sign_statement_using_xmlsec(soap_message, _signed = self.sec.sign_statement_using_xmlsec(soap_message,
@ -301,14 +300,11 @@ class HTTPBase(object):
logger.info("HTTPClient exception: %s" % (exc,)) logger.info("HTTPClient exception: %s" % (exc,))
raise raise
if response: if response.status_code == 200:
if response.status_code == 200: logger.info("SOAP response: %s" % response.text)
logger.info("SOAP response: %s" % response.text) return response
return response
else:
raise HTTPError("%d:%s" % (response.status_code, response.error))
else: else:
return None raise HTTPError("%d:%s" % (response.status_code, response.error))
def add_credentials(self, user, passwd): def add_credentials(self, user, passwd):
self.user = user self.user = user

View File

@ -146,6 +146,7 @@ def make_soap_enveloped_saml_thingy(thingy, header_parts=None):
header.tag = '{%s}Header' % NAMESPACE header.tag = '{%s}Header' % NAMESPACE
envelope.append(header) envelope.append(header)
for part in header_parts: for part in header_parts:
# This doesn't work if the headers are signed
part.become_child_element_of(header) part.become_child_element_of(header)
body = ElementTree.Element('') body = ElementTree.Element('')

View File

@ -187,7 +187,7 @@ class Server(Entity):
""" """
return self._parse_request(xml_string, NameIDMappingRequest, return self._parse_request(xml_string, NameIDMappingRequest,
"manage_name_id_service", binding) "name_id_mapping_service", binding)
# ------------------------------------------------------------------------ # ------------------------------------------------------------------------

View File

@ -110,6 +110,10 @@ def parse_soap_enveloped_saml_authn_query_response(text):
tags = ['{%s}Response' % SAMLP_NAMESPACE] tags = ['{%s}Response' % SAMLP_NAMESPACE]
return parse_soap_enveloped_saml_thingy(text, tags) return parse_soap_enveloped_saml_thingy(text, tags)
def parse_soap_enveloped_saml_authn_response(text):
tags = ['{%s}Response' % SAMLP_NAMESPACE]
return parse_soap_enveloped_saml_thingy(text, tags)
#def parse_soap_enveloped_saml_logout_response(text): #def parse_soap_enveloped_saml_logout_response(text):
# expected_tag = '{%s}LogoutResponse' % SAMLP_NAMESPACE # expected_tag = '{%s}LogoutResponse' % SAMLP_NAMESPACE

View File

@ -98,7 +98,7 @@ def test_complete_flow():
idp = Server(config_file="idp_all_conf") idp = Server(config_file="idp_all_conf")
IDP_ENTITY_ID = idp.config.entityid IDP_ENTITY_ID = idp.config.entityid
SP_ENTITY_ID = sp.config.entityid #SP_ENTITY_ID = sp.config.entityid
# ------------ @Client ----------------------------- # ------------ @Client -----------------------------
@ -170,11 +170,12 @@ def test_complete_flow():
if item.c_tag == "Response" and item.c_namespace == ecp_prof.NAMESPACE: if item.c_tag == "Response" and item.c_namespace == ecp_prof.NAMESPACE:
_ecp_response = item _ecp_response = item
_acs_url = _ecp_response.assertion_consumer_service_url #_acs_url = _ecp_response.assertion_consumer_service_url
# done phase2 at the client # done phase2 at the client
ht_args = client.use_soap(idp_response, cargs["rc_url"], [cargs["relay_state"]]) ht_args = client.use_soap(idp_response, cargs["rc_url"],
[cargs["relay_state"]])
print ht_args print ht_args