1#! /usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# $Id: idwsf2_tests.py 3254 2007-06-05 21:23:57Z dlaniel $
5#
6# Python unit tests for Lasso library
7#
8# Copyright (C) 2004-2007 Entr'ouvert
9# http://lasso.entrouvert.org
10#
11# Authors: See AUTHORS file in top-level directory.
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License as published by
15# the Free Software Foundation; either version 2 of the License, or
16# (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, see <http://www.gnu.org/licenses/>.
25
26
27import os
28import unittest
29import sys
30from six import StringIO
31import logging
32
33logging.basicConfig()
34
35if not '..' in sys.path:
36    sys.path.insert(0, '..')
37if not '../.libs' in sys.path:
38    sys.path.insert(0, '../.libs')
39
40import lasso
41
42try:
43    import lxml.etree as ET
44except ImportError:
45    try:
46        import elementtree.ElementTree as ET
47    except ImportError:
48        import xml.etree.ElementTree as ET
49
50try:
51    dataDir
52except NameError:
53    dataDir = os.path.join(os.environ['TOP_SRCDIR'], 'tests', 'data')
54
55idpSoapEndpoint = 'http://idp1/soapEndpoint'
56spSoapEndpoint = 'http://sp1/soapEndpoint'
57spInteractionUrl = 'http://sp1/askMeAQuestion'
58
59class IdWsf2TestCase(unittest.TestCase):
60    def getWspServer(self):
61        wsp_metadata = os.path.join(dataDir, 'sp5-saml2/metadata.xml')
62        wsp_private_key = os.path.join(dataDir, 'sp5-saml2/private-key.pem')
63        idp_metadata = os.path.join(dataDir, 'idp5-saml2/metadata.xml')
64
65        server = lasso.Server(wsp_metadata, wsp_private_key, None, None)
66        server.role = lasso.PROVIDER_ROLE_SP
67        server.addProvider(lasso.PROVIDER_ROLE_IDP, idp_metadata, None, None)
68        server.setEncryptionPrivateKey(wsp_private_key);
69
70        return server;
71
72    def getWscServer(self):
73        wsc_metadata = os.path.join(dataDir, 'sp6-saml2/metadata.xml')
74        wsc_private_key = os.path.join(dataDir, 'sp6-saml2/private-key.pem')
75        idp_metadata = os.path.join(dataDir, 'idp5-saml2/metadata.xml')
76
77        server = lasso.Server(wsc_metadata, wsc_private_key, None, None)
78        server.role = lasso.PROVIDER_ROLE_SP
79        server.addProvider(lasso.PROVIDER_ROLE_IDP, idp_metadata, None, None)
80
81        return server;
82
83    def getIdpServer(self):
84        if hasattr(self, 'idp_server_dump') and self.idp_server_dump is not None:
85            server = lasso.Server.newFromDump(self.idp_server_dump)
86            server.role = lasso.PROVIDER_ROLE_IDP
87        else:
88            idp_metadata = os.path.join(dataDir, 'idp5-saml2/metadata.xml')
89            idp_private_key = os.path.join(dataDir, 'idp5-saml2/private-key.pem')
90            wsp_metadata = os.path.join(dataDir, 'sp5-saml2/metadata.xml')
91            wsc_metadata = os.path.join(dataDir, 'sp6-saml2/metadata.xml')
92
93            server = lasso.Server(idp_metadata, idp_private_key, None, None)
94            server.role = lasso.PROVIDER_ROLE_IDP
95            server.addProvider(lasso.PROVIDER_ROLE_SP, wsp_metadata, None, None)
96            server.getProvider(server.providerIds[0]).setEncryptionMode(lasso.ENCRYPTION_MODE_NAMEID);
97            server.addProvider(lasso.PROVIDER_ROLE_SP, wsc_metadata, None, None)
98            self.idp_server_dump = server.dump()
99
100        return server
101
102    def query(self, wsc, idp, idp_identity_dump, wsc_session_dump, uid, federations, services_map, service_associations, provider_ids = None, service_types = None, options = None, actions = None):
103        session = lasso.Session.newFromDump(wsc_session_dump)
104        assertion = session.getAssertion(idp.providerId)
105        self.failUnless(assertion is not None)
106        epr = assertion.idwsf2GetDiscoveryBootstrapEpr()
107        self.failUnless(epr is not None)
108        wsc_disco = lasso.IdWsf2Discovery(wsc)
109        wsc_disco.setEpr(epr)
110        wsc_disco.initQuery()
111        wsc_disco.addRequestedService(service_types = service_types, provider_ids = provider_ids, options = options, actions = actions)
112        wsc_disco.buildRequestMsg()
113        idp_disco = lasso.IdWsf2Discovery(idp)
114        idp_disco.setIdentityFromDump(idp_identity_dump)
115        idp_disco.processRequestMsg(wsc_disco.msgBody)
116        f = self.nid2tuple(idp_disco.getNameIdentifier())
117        uid = federations[f]
118        for id in service_associations[uid]:
119            idp_disco.addServiceMetadata(services_map[id])
120        idp_disco.validateRequest()
121        idp_disco.buildResponseMsg()
122        wsc_disco.processResponseMsg(idp_disco.msgBody)
123        return wsc_disco.endpointReferences
124
125
126
127    def metadataRegister(self, wsp, idp, session_dump, abstract = None, address = None, provider_id = None, service_types = None, services_map = None):
128        session = lasso.Session.newFromDump(session_dump)
129        assertion = session.getAssertion(idp.providerId)
130        self.failUnless(assertion is not None)
131        epr = assertion.idwsf2GetDiscoveryBootstrapEpr()
132        self.failUnless(epr is not None)
133        wsp_disco = lasso.IdWsf2Discovery(wsp)
134        wsp_disco.setEpr(epr)
135        abstract = 'Personal Profile service'
136        self.failUnless(abstract is not None)
137        self.failUnless(address is not None)
138        self.failUnless(service_types is not None)
139        self.failUnless(isinstance(services_map, dict))
140        wsp_disco.initMetadataRegister()
141        if not provider_id:
142            provider_id = wsp.providerId
143        wsp_disco.addSimpleServiceMetadata(
144                service_types = service_types,
145                abstract = abstract, provider_id = provider_id,
146                address = address,
147                security_mechanisms = (lasso.SECURITY_MECH_BEARER,))
148        wsp_disco.buildRequestMsg()
149
150        idp_disco = lasso.IdWsf2Discovery(idp)
151        idp_disco.processRequestMsg(wsp_disco.msgBody)
152        idp_disco.checkSecurityMechanism()
153        idp_disco.validateRequest()
154        self.failUnlessEqual(len(idp_disco.metadatas), 1)
155        # add metadatas to directory
156        sender = idp_disco.getSoapEnvelopeRequest().sb2GetProviderId()
157        self.failUnless(sender is not None)
158        metadatas = services_map.get(sender, [])
159        for metadata in idp_disco.metadatas:
160            services_map[metadata.svcMDID] = metadata
161            metadatas.append(metadata.svcMDID)
162        services_map[sender] = metadatas
163        idp_disco.buildResponseMsg()
164        wsp_disco.processResponseMsg(idp_disco.msgBody)
165        self.failUnlessEqual(len(wsp_disco.metadatas), 1)
166        self.failUnlessEqual(wsp_disco.metadatas[0].svcMDID, wsp_disco.response.svcMDID[0])
167        return wsp_disco.metadatas[0].svcMDID
168
169    def nid2tuple(self, nid):
170        return (nid.nameQualifier, nid.format, nid.sPNameQualifier, nid.content)
171
172    def addAssociation(self, wsp, idp, session_dump, svcmdid, service_maps, federations, service_associations):
173        self.failUnless(isinstance(service_associations, dict))
174        self.failUnless(isinstance(service_maps, dict))
175        # Get the bootstrap
176        session = lasso.Session.newFromDump(session_dump)
177        assertion = session.getAssertion(idp.providerId)
178        self.failUnless(assertion is not None)
179        epr = assertion.idwsf2GetDiscoveryBootstrapEpr()
180        self.failUnless(epr is not None)
181        wsp_disco = lasso.IdWsf2Discovery(wsp)
182        wsp_disco.setEpr(epr)
183        wsp_disco.initMetadataAssociationAdd()
184        wsp_disco.svcmdids = (svcmdid,)
185        wsp_disco.buildRequestMsg()
186        # Handle request
187        idp_disco = lasso.IdWsf2Discovery(idp)
188        idp_disco.processRequestMsg(wsp_disco.msgBody)
189        idp_disco.checkSecurityMechanism()
190        self.failUnlessEqual(idp_disco.svcmdids, (svcmdid,))
191        sender = idp_disco.getSoapEnvelopeRequest().sb2GetProviderId()
192        name_identifier = idp_disco.getNameIdentifier()
193        f = self.nid2tuple(name_identifier)
194        uid = federations[f]
195        l = service_associations.get(uid, [])
196        for id in idp_disco.svcmdids:
197            # check it exists
198            self.failUnless(service_maps.get(id) is not None)
199            # create association
200            if id not in l:
201                l.append(id)
202        service_associations[uid] = l
203        idp_disco.validateRequest()
204        idp_disco.buildResponseMsg()
205        wsp_disco.processResponseMsg(idp_disco.msgBody)
206
207    def login(self, sp, idp, user_id, federations, sp_identity_dump=None, sp_session_dump=None,
208            idp_identity_dump=None, idp_session_dump=None):
209        sp_login = lasso.Login(sp)
210        idp_provider_id = 'http://idp5/metadata'
211        sp_login.initAuthnRequest(idp_provider_id, lasso.HTTP_METHOD_REDIRECT)
212        sp_login.request.nameIDPolicy.format = lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT
213        sp_login.request.nameIDPolicy.allowCreate = True
214        sp_login.buildAuthnRequestMsg()
215
216        idp_login = lasso.Login(idp)
217        query = sp_login.msgUrl.split('?')[1]
218        if idp_identity_dump is not None:
219            idp_login.setIdentityFromDump(idp_identity_dump)
220        if idp_session_dump is not None:
221            idp_login.setSessionFromDump(idp_session_dump)
222        idp_login.processAuthnRequestMsg(query)
223        idp_login.validateRequestMsg(True, True)
224        idp_login.buildAssertion(lasso.SAML_AUTHENTICATION_METHOD_PASSWORD, None, None, None, None)
225        if idp_login.assertion.subject.encryptedId:
226            f = self.nid2tuple(idp_login.assertion.subject.encryptedId.originalData)
227        else:
228            f = self.nid2tuple(idp_login.assertion.subject.nameId)
229        federations[f] = user_id
230        l = federations.get(user_id, [])
231        l.append(f)
232        federations[user_id] = l
233        idp_login.idwsf2AddDiscoveryBootstrapEpr(url = idpSoapEndpoint, abstract = 'Discovery Service', security_mechanisms = (lasso.SECURITY_MECH_BEARER,))
234        idp_login.buildArtifactMsg(lasso.HTTP_METHOD_ARTIFACT_GET)
235        artifact_message = idp_login.artifactMessage
236
237        if idp_login.isIdentityDirty:
238            idp_identity_dump = idp_login.identity.dump()
239        if idp_login.isSessionDirty:
240            idp_session_dump = idp_login.session.dump()
241
242        sp_login = lasso.Login(sp)
243        query = idp_login.msgUrl.split('?')[1]
244        query = query.replace("%3D", "=")
245        sp_login.initRequest(query, lasso.HTTP_METHOD_ARTIFACT_GET)
246        sp_login.buildRequestMsg()
247
248        idp_login = lasso.Login(idp)
249        idp_login.processRequestMsg(sp_login.msgBody)
250        idp_login.artifactMessage = artifact_message
251        idp_login.buildResponseMsg(None)
252
253        sp_login.processResponseMsg(idp_login.msgBody)
254        sp_login.acceptSso()
255        if sp_login.isIdentityDirty:
256            sp_identity_dump = sp_login.identity.dump()
257        if sp_login.isSessionDirty:
258            sp_session_dump = sp_login.session.dump()
259
260        return sp_identity_dump, sp_session_dump, idp_identity_dump, idp_session_dump, sp_login.idwsf2GetDiscoveryBootstrapEpr()
261
262
263class MetadataTestCase(IdWsf2TestCase):
264    def test01(self):
265        """Test metadata registration on the IdP"""
266        idp = self.getIdpServer()
267        wsp = self.getWspServer()
268        wsp_identity_dump, wsp_session_dump, idp_identity_dump, idp_session_dump, dst_epr = self.login(wsp, idp, 1, {})
269
270        wsp_disco = lasso.IdWsf2Discovery(wsp)
271        wsp_disco.setEpr(dst_epr)
272
273        abstract = 'Personal Profile service'
274        wsp_disco.initMetadataRegister()
275        self.failUnless(wsp_disco.request is not None)
276        wsp_disco.addSimpleServiceMetadata(service_types =
277                (lasso.PP11_HREF,), abstract = abstract,
278                provider_id = wsp.providerId, address = spSoapEndpoint,
279                security_mechanisms = (lasso.SECURITY_MECH_BEARER,))
280        self.failUnlessEqual(len(wsp_disco.metadatas), 1)
281        metadata = wsp_disco.metadatas[0]
282        self.failUnlessEqual(metadata.abstract, abstract)
283        self.failUnlessEqual(metadata.providerId, wsp.providerId)
284        self.failUnlessEqual(len(metadata.serviceContext), 1)
285        self.failUnlessEqual(len(metadata.serviceContext[0].serviceType), 1)
286        self.failUnlessEqual(metadata.serviceContext[0].serviceType[0],
287                lasso.PP11_HREF)
288        self.failUnlessEqual(len(metadata.serviceContext[0].endpointContext), 1)
289        self.failUnlessEqual(
290                len(metadata.serviceContext[0].endpointContext[0].address),
291                1)
292        self.failUnlessEqual(metadata.serviceContext[0].endpointContext[0].address[0],
293                spSoapEndpoint)
294        self.failUnlessEqual(
295                len(metadata.serviceContext[0].endpointContext[0].securityMechId),
296                1)
297        self.failUnlessEqual(
298                metadata.serviceContext[0].endpointContext[0].securityMechId[0],
299                lasso.SECURITY_MECH_BEARER)
300        self.failUnless(metadata.svcMDID is None)
301        wsp_disco.buildRequestMsg()
302        self.failUnlessEqual(wsp_disco.msgUrl, idpSoapEndpoint)
303        self.failUnless(wsp_disco.msgBody is not None)
304
305        idp_disco = lasso.IdWsf2Discovery(idp)
306        self.failUnless(idp_disco is not None)
307        idp_disco.processRequestMsg(wsp_disco.msgBody)
308        self.failUnless(idp_disco.request is not None)
309        self.failUnlessEqual(len(idp_disco.request.svcMD), 1)
310        self.failUnless(idp_disco.request.svcMD[0].svcMDID is None)
311        try:
312            idp_disco.checkSecurityMechanism()
313        except lasso.Error as e:
314            self.fail(e)
315        try:
316            idp_disco.validateRequest()
317        except lasso.Error as e:
318            self.fail(e)
319        self.failUnless(idp_disco.response is not None)
320        self.failUnlessEqual(len(idp_disco.metadatas), 1)
321        metadata = idp_disco.metadatas[0]
322        self.failUnlessEqual(metadata.abstract, abstract)
323        self.failUnlessEqual(metadata.providerId, wsp.providerId)
324        self.failUnlessEqual(len(metadata.serviceContext), 1)
325        self.failUnlessEqual(len(metadata.serviceContext[0].serviceType), 1)
326        self.failUnlessEqual(metadata.serviceContext[0].serviceType[0],
327                lasso.PP11_HREF)
328        self.failUnlessEqual(len(metadata.serviceContext[0].endpointContext), 1)
329        self.failUnlessEqual(
330                len(metadata.serviceContext[0].endpointContext[0].address),
331                1)
332        self.failUnlessEqual(metadata.serviceContext[0].endpointContext[0].address[0],
333                spSoapEndpoint)
334        self.failUnlessEqual(
335                len(metadata.serviceContext[0].endpointContext[0].securityMechId),
336                1)
337        self.failUnlessEqual(
338                metadata.serviceContext[0].endpointContext[0].securityMechId[0],
339                lasso.SECURITY_MECH_BEARER)
340        idp_disco.buildResponseMsg()
341        self.failUnless(metadata.svcMDID is not None)
342        self.failUnless(idp_disco.msgUrl is None)
343        self.failUnless(idp_disco.msgBody is not None)
344
345        wsp_disco.processResponseMsg(idp_disco.msgBody)
346
347        self.failUnless(len(wsp_disco.metadatas) == 1, 'missing svcMDID')
348        self.failUnless(wsp_disco.metadatas[0].svcMDID, 'missing svcMDID')
349
350    def test02(self):
351        "Test failure by IdP for register request"
352        idp = self.getIdpServer()
353        wsp = self.getWspServer()
354        wsp_identity_dump, wsp_session_dump, idp_identity_dump, idp_session_dump, dst_epr = self.login(wsp, idp, 1, {})
355
356        wsp_disco = lasso.IdWsf2Discovery(wsp)
357        wsp_disco.setEpr(dst_epr)
358
359        abstract = 'Personal Profile service'
360        wsp_disco.initMetadataRegister()
361        self.failUnless(wsp_disco.request is not None)
362        wsp_disco.addSimpleServiceMetadata(service_types =
363                (lasso.PP11_HREF,), abstract = abstract,
364                provider_id = wsp.providerId, address = spSoapEndpoint,
365                security_mechanisms= (lasso.SECURITY_MECH_BEARER,))
366        self.failUnlessEqual(len(wsp_disco.metadatas), 1)
367        metadata = wsp_disco.metadatas[0]
368        self.failUnlessEqual(metadata.abstract, abstract)
369        self.failUnlessEqual(metadata.providerId, wsp.providerId)
370        self.failUnlessEqual(len(metadata.serviceContext[0].serviceType), 1)
371        self.failUnlessEqual(metadata.serviceContext[0].serviceType[0],
372                lasso.PP11_HREF)
373        self.failUnlessEqual(len(metadata.serviceContext[0].endpointContext), 1)
374        self.failUnlessEqual(
375                len(metadata.serviceContext[0].endpointContext[0].address),
376                1)
377        self.failUnlessEqual(metadata.serviceContext[0].endpointContext[0].address[0],
378                spSoapEndpoint)
379        self.failUnlessEqual(
380                len(metadata.serviceContext[0].endpointContext[0].securityMechId),
381                1)
382        self.failUnlessEqual(
383                metadata.serviceContext[0].endpointContext[0].securityMechId[0],
384                lasso.SECURITY_MECH_BEARER)
385        self.failUnless(metadata.svcMDID is None)
386        wsp_disco.buildRequestMsg()
387        self.failUnlessEqual(wsp_disco.msgUrl, idpSoapEndpoint)
388        self.failUnless(wsp_disco.msgBody is not None)
389
390        idp_disco = lasso.IdWsf2Discovery(idp)
391        self.failUnless(idp_disco is not None)
392        try:
393            idp_disco.processRequestMsg(wsp_disco.msgBody)
394        except lasso.Error as e:
395            self.fail(e)
396        self.failUnless(idp_disco.request is not None)
397        try:
398            idp_disco.checkSecurityMechanism()
399        except lasso.Error as e:
400            self.fail(e)
401        try:
402            idp_disco.failRequest(lasso.IDWSF2_DISCOVERY_STATUS_CODE_FAILED, lasso.IDWSF2_DISCOVERY_STATUS_CODE_FORBIDDEN)
403        except lasso.Error as e:
404            self.fail(e)
405        self.failUnless(idp_disco.response is not None)
406        self.failUnless(idp_disco.response.status is not None)
407        self.failUnless(idp_disco.response.status.code is not lasso.IDWSF2_DISCOVERY_STATUS_CODE_FAILED)
408        self.failUnlessEqual(len(idp_disco.response.status.status), 1)
409        self.failUnless(idp_disco.response.status.status[0].code is not lasso.IDWSF2_DISCOVERY_STATUS_CODE_FORBIDDEN)
410        idp_disco.buildResponseMsg()
411        self.failUnless(idp_disco.msgUrl is None)
412        self.failUnless(idp_disco.msgBody is not None)
413
414        try:
415            wsp_disco.processResponseMsg(idp_disco.msgBody)
416        except lasso.Idwsf2DiscoveryForbiddenError:
417            pass
418        except lasso.Error as e:
419            self.fail(e)
420
421    def test03(self):
422        """Test metadata register with redirection"""
423        idp = self.getIdpServer()
424        wsp = self.getWspServer()
425        wsp_identity_dump, wsp_session_dump, idp_identity_dump, idp_session_dump, dst_epr = self.login(wsp, idp, 1, {})
426
427        wsp_disco = lasso.IdWsf2Discovery(wsp)
428        wsp_disco.setEpr(dst_epr)
429
430        abstract = 'Personal Profile service'
431        wsp_disco.initMetadataRegister()
432        soap_envelope = wsp_disco.getSoapEnvelopeRequest()
433        soap_envelope.setSb2UserInteractionHint(lasso.IDWSF2_SB2_USER_INTERACTION_HINT_INTERACT_IF_NEEDED)
434        self.failUnless(isinstance(soap_envelope.header, lasso.SoapHeader))
435        self.failUnless(len(soap_envelope.header.other) > 0)
436        self.failUnlessEqual(soap_envelope.getSb2UserInteractionHint(), lasso.IDWSF2_SB2_USER_INTERACTION_HINT_INTERACT_IF_NEEDED)
437        self.failUnless(wsp_disco.request is not None)
438        wsp_disco.addSimpleServiceMetadata(service_types =
439                (lasso.PP11_HREF,), abstract = abstract,
440                provider_id = wsp.providerId, address = spSoapEndpoint,
441                security_mechanisms = (lasso.SECURITY_MECH_BEARER,))
442        self.failUnlessEqual(len(wsp_disco.metadatas), 1)
443        metadata = wsp_disco.metadatas[0]
444        self.failUnlessEqual(metadata.abstract, abstract)
445        self.failUnlessEqual(metadata.providerId, wsp.providerId)
446        self.failUnlessEqual(len(metadata.serviceContext), 1)
447        self.failUnlessEqual(len(metadata.serviceContext[0].serviceType), 1)
448        self.failUnlessEqual(metadata.serviceContext[0].serviceType[0],
449                lasso.PP11_HREF)
450        self.failUnlessEqual(len(metadata.serviceContext[0].endpointContext), 1)
451        self.failUnlessEqual(
452                len(metadata.serviceContext[0].endpointContext[0].address),
453                1)
454        self.failUnlessEqual(metadata.serviceContext[0].endpointContext[0].address[0],
455                spSoapEndpoint)
456        self.failUnlessEqual(
457                len(metadata.serviceContext[0].endpointContext[0].securityMechId),
458                1)
459        self.failUnlessEqual(
460                metadata.serviceContext[0].endpointContext[0].securityMechId[0],
461                lasso.SECURITY_MECH_BEARER)
462        self.failUnless(metadata.svcMDID is None)
463        wsp_disco.buildRequestMsg()
464        self.failUnlessEqual(wsp_disco.msgUrl, idpSoapEndpoint)
465        self.failUnless(wsp_disco.msgBody is not None)
466
467        idp_disco = lasso.IdWsf2Discovery(idp)
468        self.failUnless(idp_disco is not None)
469        idp_disco.processRequestMsg(wsp_disco.msgBody)
470        self.failUnless(idp_disco.request is not None)
471        self.failUnlessEqual(len(idp_disco.request.svcMD), 1)
472        self.failUnless(idp_disco.request.svcMD[0].svcMDID is None)
473        soap_envelope = idp_disco.getSoapEnvelopeRequest()
474        self.failUnless(soap_envelope is not None)
475        self.failUnless(soap_envelope.getMessageId() is not None)
476        try:
477            idp_disco.checkSecurityMechanism()
478        except lasso.Error as e:
479            self.fail(e)
480        # redirect
481        interactionUrl = spInteractionUrl
482        idp_disco.redirectUserForInteraction(interactionUrl, False)
483        response = idp_disco.response
484        self.failUnless(isinstance(response, lasso.SoapFault))
485        self.failUnless(response.detail is not None)
486        self.failUnlessEqual(len(response.detail.any), 1)
487        self.failUnless(isinstance(response.detail.any[0], lasso.IdWsf2Sb2RedirectRequest))
488        self.failUnless(response.detail.any[0].redirectURL.startswith(interactionUrl + '?transactionID='))
489        try:
490            idp_disco.buildResponseMsg()
491        except lasso.Error as e:
492            self.fail(e)
493        self.failUnless(idp_disco.msgBody is not None)
494
495
496        self.failUnless(idp_disco.msgUrl is None)
497        self.failUnless(idp_disco.msgBody is not None)
498
499        try:
500            wsp_disco.processResponseMsg(idp_disco.msgBody)
501        except lasso.WsfprofileRedirectRequestError:
502            pass
503        except lasso.Error as e:
504            self.fail(e)
505        response_envelope = wsp_disco.getSoapEnvelopeResponse()
506        self.failUnless(response_envelope.sb2GetRedirectRequestUrl().startswith(interactionUrl + '?transactionID='))
507        # Here keep information about the request associated to ID: response_envelope.getMessageId().content
508        wsp_disco_dump = wsp_disco.dump()
509        wsp_disco = lasso.Node.newFromDump(wsp_disco_dump)
510        wsp_disco.server = wsp
511        request_envelope = wsp_disco.getSoapEnvelopeRequest()
512        self.failUnless(request_envelope is not None)
513        relates_to = request_envelope.getRelatesTo(True)
514        self.failUnless(relates_to is not None)
515        response_message_id = response_envelope.getMessageId().content
516        relates_to.content = response_message_id
517        wsp_disco.buildRequestMsg()
518        # now redo as for test01 after request building
519        self.failUnlessEqual(wsp_disco.msgUrl, idpSoapEndpoint)
520        self.failUnless(wsp_disco.msgBody is not None)
521
522        idp_disco = lasso.IdWsf2Discovery(idp)
523        self.failUnless(idp_disco is not None)
524        idp_disco.processRequestMsg(wsp_disco.msgBody)
525        self.failUnless(idp_disco.request is not None)
526        self.failUnlessEqual(len(idp_disco.request.svcMD), 1)
527        self.failUnless(idp_disco.request.svcMD[0].svcMDID is None)
528        try:
529            idp_disco.checkSecurityMechanism()
530        except lasso.Error as e:
531            self.fail(e)
532        try:
533            idp_disco.validateRequest()
534        except lasso.Error as e:
535            self.fail(e)
536        self.failUnless(idp_disco.response is not None)
537        self.failUnlessEqual(len(idp_disco.metadatas), 1)
538        metadata = idp_disco.metadatas[0]
539        self.failUnlessEqual(metadata.abstract, abstract)
540        self.failUnlessEqual(metadata.providerId, wsp.providerId)
541        self.failUnlessEqual(len(metadata.serviceContext), 1)
542        self.failUnlessEqual(len(metadata.serviceContext[0].serviceType), 1)
543        self.failUnlessEqual(metadata.serviceContext[0].serviceType[0],
544                lasso.PP11_HREF)
545        self.failUnlessEqual(len(metadata.serviceContext[0].endpointContext), 1)
546        self.failUnlessEqual(
547                len(metadata.serviceContext[0].endpointContext[0].address),
548                1)
549        self.failUnlessEqual(metadata.serviceContext[0].endpointContext[0].address[0],
550                spSoapEndpoint)
551        self.failUnlessEqual(
552                len(metadata.serviceContext[0].endpointContext[0].securityMechId),
553                1)
554        self.failUnlessEqual(
555                metadata.serviceContext[0].endpointContext[0].securityMechId[0],
556                lasso.SECURITY_MECH_BEARER)
557        idp_disco.buildResponseMsg()
558        self.failUnless(metadata.svcMDID is not None)
559        self.failUnless(idp_disco.msgUrl is None)
560        self.failUnless(idp_disco.msgBody is not None)
561
562        wsp_disco.processResponseMsg(idp_disco.msgBody)
563
564        self.failUnless(len(wsp_disco.metadatas) == 1, 'missing svcMDID')
565        self.failUnless(wsp_disco.metadatas[0].svcMDID, 'missing svcMDID')
566
567    def test04(self):
568        """Test metadata query"""
569        idp = self.getIdpServer()
570        wsp = self.getWspServer()
571        federations = {}
572        wsp_identity_dump, wsp_session_dump, idp_identity_dump, idp_session_dump, dst_epr = self.login(wsp, idp, 1, federations)
573        service_map = {}
574        self.metadataRegister(wsp, idp, wsp_session_dump, service_types =
575            (lasso.PP11_HREF,), address = spSoapEndpoint,
576            abstract = 'My first PP service', services_map = service_map)
577        self.metadataRegister(wsp, idp, wsp_session_dump, service_types =
578            (lasso.PP11_HREF,), address = spSoapEndpoint+'2',
579            abstract = 'My second PP service', services_map = service_map)
580        wsp_identity_dump, wsp_session_dump, idp_identity_dump, idp_session_dump, dst_epr = self.login(wsp, idp, 1, federations)
581        wsp_disco = lasso.IdWsf2Discovery(wsp)
582        wsp_disco.setEpr(dst_epr)
583        wsp_disco.initMetadataQuery()
584        wsp_disco.buildRequestMsg()
585
586        idp_disco = lasso.IdWsf2Discovery(idp)
587        idp_disco.processRequestMsg(wsp_disco.msgBody)
588        idp_disco.checkSecurityMechanism()
589        self.failUnlessEqual(idp_disco.svcmdids, ())
590        sender = idp_disco.getSoapEnvelopeRequest().sb2GetProviderId()
591        for svcMDID in service_map.get(sender, []):
592            idp_disco.addServiceMetadata(service_map.get(svcMDID))
593        idp_disco.validateRequest()
594        idp_disco.buildResponseMsg()
595        wsp_disco.processResponseMsg(idp_disco.msgBody)
596        self.failUnless(len(wsp_disco.metadatas), 2)
597
598    def test05(self):
599        """Test metadata delete"""
600        idp = self.getIdpServer()
601        wsp = self.getWspServer()
602        wsp_identity_dump, wsp_session_dump, idp_identity_dump, idp_session_dump, dst_epr = self.login(wsp, idp, 1, {})
603        service_map = {}
604        self.metadataRegister(wsp, idp, wsp_session_dump, service_types =
605            (lasso.PP11_HREF,), address = spSoapEndpoint,
606            abstract = 'My first PP service', services_map = service_map)
607        self.metadataRegister(wsp, idp, wsp_session_dump, service_types =
608            (lasso.PP11_HREF,), address = spSoapEndpoint+'2',
609            abstract = 'My second PP service', services_map = service_map)
610        wsp_identity_dump, wsp_session_dump, idp_identity_dump, idp_session_dump, dst_epr = self.login(wsp, idp, 1, {})
611
612        wsp_disco = lasso.IdWsf2Discovery(wsp)
613        wsp_disco.setEpr(dst_epr)
614        wsp_disco.initMetadataDelete()
615        svcmdids = tuple(service_map[wsp.providerId])
616        wsp_disco.setSvcmdids(svcmdids)
617        wsp_disco.buildRequestMsg()
618
619        idp_disco = lasso.IdWsf2Discovery(idp)
620        idp_disco.processRequestMsg(wsp_disco.msgBody)
621        idp_disco.checkSecurityMechanism()
622        self.failUnlessEqual(idp_disco.svcmdids, svcmdids)
623        sender = idp_disco.getSoapEnvelopeRequest().sb2GetProviderId()
624        self.failUnlessEqual(sender, wsp.providerId)
625        idp_disco.validateRequest()
626        idp_disco.buildResponseMsg()
627        wsp_disco.processResponseMsg(idp_disco.msgBody)
628
629class MetadataAssociationTestCase(IdWsf2TestCase):
630    def test01(self):
631        """Metadata association add"""
632        idp = self.getIdpServer()
633        wsp = self.getWspServer()
634        wsp_identity_dump, wsp_session_dump, idp_identity_dump, idp_session_dump, dst_epr = self.login(wsp, idp, 1, {})
635        service_map = {}
636        svcMDID = self.metadataRegister(wsp, idp, wsp_session_dump, service_types =
637            (lasso.PP11_HREF,), address = spSoapEndpoint,
638            abstract = 'My first PP service', services_map = service_map)
639        # Make the request
640        wsp_disco = lasso.IdWsf2Discovery(wsp)
641        wsp_disco.setEpr(dst_epr)
642        wsp_disco.initMetadataAssociationAdd()
643        wsp_disco.svcmdids = (svcMDID,)
644        wsp_disco.buildRequestMsg()
645        # Receive it
646        idp_disco = lasso.IdWsf2Discovery(idp)
647        idp_disco.processRequestMsg(wsp_disco.msgBody)
648        idp_disco.checkSecurityMechanism()
649        self.failUnlessEqual(idp_disco.svcmdids, (svcMDID,))
650        sender = idp_disco.getSoapEnvelopeRequest().sb2GetProviderId()
651        name_identifier = idp_disco.getNameIdentifier()
652        # Store the association
653        self.failUnless(sender is not None)
654        self.failUnless(name_identifier is not None)
655        idp_disco.validateRequest()
656        idp_disco.buildResponseMsg()
657        wsp_disco.processResponseMsg(idp_disco.msgBody)
658
659    def test02(self):
660        """Metadata association query"""
661        idp = self.getIdpServer()
662        wsp = self.getWspServer()
663        wsc = self.getWscServer()
664        # Register the service, add an association
665        federations = {}
666        wsp_identity_dump, wsp_session_dump, \
667                idp_identity_dump, idp_session_dump, \
668                wsp_dst_epr = self.login(wsp, idp, 1, federations)
669        service_maps = {}
670        svcMDID = self.metadataRegister(wsp, idp, wsp_session_dump,
671                service_types = (lasso.PP11_HREF,), address = spSoapEndpoint,
672            abstract = 'My first PP service', services_map = service_maps)
673        service_associations = {}
674        self.addAssociation(wsp, idp, wsp_session_dump, svcMDID, service_maps,
675                federations, service_associations)
676        # Start a query
677        wsp_disco = lasso.IdWsf2Discovery(wsp)
678        wsp_disco.setEpr(wsp_dst_epr)
679        wsp_disco.initMetadataAssociationQuery()
680        wsp_disco.buildRequestMsg()
681        #
682        idp_disco = lasso.IdWsf2Discovery(idp)
683        idp_disco.processRequestMsg(wsp_disco.msgBody)
684        idp_disco.checkSecurityMechanism()
685        self.failUnlessEqual(idp_disco.svcmdids, ())
686        f = self.nid2tuple(idp_disco.getNameIdentifier())
687        uid = federations[f]
688        result = []
689        for svcmdid in service_associations[uid]:
690            result.append(svcmdid)
691        idp_disco.svcmdids = tuple(result)
692        idp_disco.validateRequest()
693        idp_disco.buildResponseMsg()
694        wsp_disco.processResponseMsg(idp_disco.msgBody)
695        self.failUnlessEqual(wsp_disco.svcmdids, (svcMDID,))
696
697    def test03(self):
698        """Metadata association delete"""
699        pass
700
701class QueryTestCase(IdWsf2TestCase):
702    def test01(self):
703        """Discovery Service Query"""
704        idp = self.getIdpServer()
705        wsp = self.getWspServer()
706        wsc = self.getWscServer()
707        federations = {}
708        # Register the service, add an association
709        wsp_identity_dump, wsp_session_dump, idp_identity_dump, idp_session_dump, wsp_dst_epr = self.login(wsp, idp, 1, federations)
710        service_maps = {}
711        svcMDID = self.metadataRegister(wsp, idp, wsp_session_dump, service_types =
712            (lasso.PP11_HREF,), address = spSoapEndpoint,
713            abstract = 'My first PP service', services_map = service_maps)
714        service_associations = {}
715        self.addAssociation(wsp, idp, wsp_session_dump, svcMDID, service_maps, federations, service_associations)
716        # Try to find the service
717        wsc_identity_dump, wsc_session_dump, idp_identity_dump, idp_session_dump, wsc_dst_epr = self.login(wsc, idp, 1, federations, idp_identity_dump = idp_identity_dump, idp_session_dump = idp_session_dump)
718        wsc_disco = lasso.IdWsf2Discovery(wsc)
719        wsc_disco.setEpr(wsc_dst_epr)
720        wsc_disco.initQuery()
721        wsc_disco.addRequestedService(service_types = (lasso.PP11_HREF,))
722        wsc_disco.buildRequestMsg()
723        idp_disco = lasso.IdWsf2Discovery(idp)
724        idp_disco.setIdentityFromDump(idp_identity_dump)
725        idp_disco.processRequestMsg(wsc_disco.msgBody)
726        f = self.nid2tuple(idp_disco.getNameIdentifier())
727        uid = federations[f]
728        for id in service_associations[uid]:
729            idp_disco.addServiceMetadata(service_maps[id])
730        idp_disco.validateRequest()
731        idp_disco.buildResponseMsg()
732        wsc_disco.processResponseMsg(idp_disco.msgBody)
733        self.failUnlessEqual(len(wsc_disco.endpointReferences), 1)
734
735class DstTestCase(IdWsf2TestCase):
736    def test01(self):
737        """Data Service Template Query"""
738        content = '<pp:PP xmlns:pp="%s">Coin</pp:PP>' % lasso.PP11_HREF
739        idp = self.getIdpServer()
740        wsp = self.getWspServer()
741        wsc = self.getWscServer()
742        federations = {}
743        # Register the service, add an association
744        wsp_identity_dump, wsp_session_dump, idp_identity_dump, \
745            idp_session_dump, wsp_dst_epr = self.login(wsp, idp, 1,
746                    federations)
747        service_maps = {}
748        svcMDID = self.metadataRegister(wsp, idp, wsp_session_dump,
749                service_types = (lasso.PP11_HREF,), address =
750                spSoapEndpoint, abstract = 'My first PP service',
751                services_map = service_maps)
752        service_associations = {}
753        self.addAssociation(wsp, idp, wsp_session_dump, svcMDID,
754                service_maps, federations, service_associations)
755        wsc_identity_dump, wsc_session_dump, idp_identity_dump, \
756        idp_session_dump, wsc_dst_epr = self.login(wsc, idp, 1, federations,
757                idp_identity_dump = idp_identity_dump, idp_session_dump =
758                idp_session_dump)
759        eprs = self.query(wsc, idp, idp_identity_dump, wsc_session_dump, 1,
760                federations, service_maps, service_associations,
761                service_types = (lasso.PP11_HREF,))
762        self.failUnless(len(eprs), 1)
763        lasso.registerIdwsf2DstService(lasso.PP11_PREFIX, lasso.PP11_HREF)
764        wsc_dst = lasso.IdWsf2DataService(wsc)
765        wsc_dst.setEpr(eprs[0])
766        wsc_dst.initQuery()
767        wsc_dst.setServiceType(lasso.PP11_PREFIX, lasso.PP11_HREF)
768        wsc_dst.addQueryItem('/%s:PP' % lasso.PP11_PREFIX, 'xxx')
769        wsc_dst.buildRequestMsg()
770        wsp_dst = lasso.IdWsf2DataService(wsp)
771        wsp_dst.processRequestMsg(wsc_dst.msgBody)
772        self.failUnlessEqual(wsp_dst.requestType, lasso.IDWSF2_DATA_SERVICE_REQUEST_TYPE_QUERY)
773        wsp_dst.checkSecurityMechanism()
774        data = ET.parse(StringIO(content))
775        for item in wsp_dst.items:
776            result = data.xpath(item.select, namespaces = { lasso.PP11_PREFIX: lasso.PP11_HREF })
777            for found in result:
778                wsp_dst.setQueryItemResult(item.itemId, ET.tostring(found), True)
779        wsp_dst.setServiceType(lasso.PP11_PREFIX, lasso.PP11_HREF)
780        wsp_dst.validateRequest()
781        wsp_dst.buildResponseMsg()
782        wsc_dst.processResponseMsg(wsp_dst.msgBody)
783
784
785metadataSuite = unittest.makeSuite(MetadataTestCase, 'test')
786metadataAssociationSuite = unittest.makeSuite(MetadataAssociationTestCase, 'test')
787querySuite = unittest.makeSuite(QueryTestCase, 'test')
788dstSuite = unittest.makeSuite(DstTestCase, 'test')
789
790
791allTests = unittest.TestSuite((metadataSuite,
792    metadataAssociationSuite,querySuite,dstSuite))
793
794if __name__ == '__main__':
795    sys.exit(not unittest.TextTestRunner(verbosity = 2).run(allTests).wasSuccessful())
796
797