source: TI12-security/trunk/python/ndg.security.server/ndg/security/server/conf/sessionMgr.tac @ 2884

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.server/ndg/security/server/conf/sessionMgr.tac@2884
Revision 2884, 8.8 KB checked in by pjkersha, 13 years ago (diff)

Explicitly setting of SSL timeout avoids hanging client for calls over https

ndg.security.server/ndg/security/server/conf/sessionMgr.tac,
ndg.security.server/ndg/security/server/conf/attAuthority.tac:

  • added ref to NDGSEC_INT_DEBUG environment variable -sets service to stop in debugger at the start of each SOAP call. Service must be restarted in order for variable to be picked up

ndg.security.test/ndg/security/test/AttAuthority/siteAAttAuthorityProperties.xml,
ndg.security.test/ndg/security/test/AttAuthority/attAuthorityClientTest.cfg,
ndg.security.test/ndg/security/test/SessionMgr/sessionMgrClientTest.cfg:

  • running unit tests with https switched on to investigate timeout problems. SM calls to an AA over https currently fail with a HTTP bad status line error

ndg.security.common/ndg/security/common/AttAuthority/init.py: improve error reporting for getAttCert call.

ndg.security.common/ndg/security/common/m2CryptoSSLUtility.py:

  • added functionality to set read and write timeouts. M2Crypto default is 600s(!). Changed default to 3s
Line 
1#!/usr/bin/env python
2"""NDG Security Session Manager .tac file
3
4This file enables the Session Manager web service to be
5called under the Twisted framework
6
7NERC Data Grid Project
8
9@author P J Kershaw 23/11/06
10
11@copyright (C) 2007 CCLRC & NERC
12
13@license This software may be distributed under the terms of the Q Public
14License, version 1.0 or later.
15"""
16import os, base64
17
18from ZSI.twisted.WSresource import WSResource
19from twisted.application import service, internet
20from twisted.web.server import Site
21from twisted.web.resource import Resource
22
23from ndg.security.server.SessionMgr.SessionMgr_services_server import \
24        SessionMgrService
25from ndg.security.server.SessionMgr import SessionMgr
26from ndg.security.common.wsSecurity import SignatureHandler
27from ndg.security.server.twisted import WSSecurityHandler, \
28        WSSecurityHandlerChainFactory
29       
30
31from ndg.security.common.X509 import X509CertRead
32
33
34class SessionMgrServiceSub(SessionMgrService, WSResource):
35
36    # Add WS-Security handlers
37    factory = WSSecurityHandlerChainFactory
38       
39    def __init__(self):
40        '''Initialize Session Manager class - encapsulates inner workings
41        including session management and proxy delegation
42       
43        @type ps: ZSI ParsedSoap
44        @param ps: client SOAP message
45        @rtype: tuple
46        @return: request and response objects'''
47
48        WSResource.__init__(self) 
49        self.sm = SessionMgr()
50       
51        # Stop in debugger at beginning of SOAP stub if environment variable
52        # is set
53        self.__debug = bool(os.environ.get('NDGSEC_INT_DEBUG'))
54
55
56    def soap_addUser(self, ps, **kw):
57        '''Add a new user account
58       
59        @type ps: ZSI ParsedSoap
60        @param ps: client SOAP message
61        @rtype: tuple
62        @return: request and response objects'''
63
64        request, response = SessionMgrService.soap_addUser(self, ps)
65        return request, response
66
67
68    def soap_connect(self, ps, **kw):
69        '''Connect to Session Manager and create a user session
70       
71        @type ps: ZSI ParsedSoap
72        @param ps: client SOAP message
73        @rtype: tuple
74        @return: request and response objects'''
75
76        if self.__debug:
77                import pdb
78                pdb.set_trace()
79               
80        request, response = SessionMgrService.soap_connect(self, ps)
81       
82        result = self.sm.connect(username=request.Username,
83                                                                 passphrase=request.Passphrase,
84                                                                 createServerSess=request.CreateServerSess)
85                                       
86        response.ProxyCert, response.ProxyPriKey, response.UserCert, \
87                response.SessID = result
88                         
89        return request, response
90
91
92    def soap_disconnect(self, ps, **kw):
93        '''Disconnect and remove user's session
94       
95        @type ps: ZSI ParsedSoap
96        @param ps: client SOAP message
97        @rtype: tuple
98        @return: request and response objects'''
99        if self.__debug:
100                import pdb
101                pdb.set_trace()
102                           
103        request, response = SessionMgrService.soap_disconnect(self, ps)
104       
105        # Derive designated user ID differently according to whether
106        # a session ID was passed and the message was signed
107        sessID = request.SessID or None
108               
109        if srv.sm['useSignatureHandler']:
110            # Get certificate corresponding to private key that signed the
111            # message - i.e. the user's proxy
112            userCert = WSSecurityHandler.signatureHandler.verifyingCert
113        else:
114            userCert = request.UserCert
115
116        self.sm.deleteUserSession(sessID=sessID, proxyCert=userCert)
117        return request, response
118
119
120    def soap_getAttCert(self, ps, **kw):
121        '''Get Attribute Certificate from a given Attribute Authority
122        and cache it in user's Credential Wallet
123       
124        @type ps: ZSI ParsedSoap
125        @param ps: client SOAP message
126        @rtype: tuple
127        @return: request and response objects'''
128        if self.__debug:
129                import pdb
130                pdb.set_trace()
131               
132        request, response = SessionMgrService.soap_getAttCert(self, ps)
133
134        # Get certificate corresponding to private key that signed the
135        # message - i.e. the user's             
136        if srv.sm['useSignatureHandler']:
137            # Get certificate corresponding to private key that signed the
138            # message - i.e. the user's proxy
139            userCert = WSSecurityHandler.signatureHandler.verifyingCert
140        else:
141            userCert = None
142       
143                # Cert used in signature is prefered over userCert input element -
144                # userCert may have been omitted.
145        result = self.sm.getAttCert(\
146                                            userCert=userCert or request.UserCert,
147                                                sessID=request.SessID,
148                                                aaURI=request.AttAuthorityURI,
149                                                reqRole=request.ReqRole,
150                                                mapFromTrustedHosts=request.MapFromTrustedHosts,
151                                                rtnExtAttCertList=request.RtnExtAttCertList,
152                                                extAttCertList=request.ExtAttCert,
153                                                extTrustedHostList=request.ExtTrustedHost)
154
155
156        if result[0]:
157                response.AttCert = result[0].toString() 
158               
159        response.Msg, response.ExtAttCertOut = result[1:]
160       
161        return request, response
162
163
164    def soap_getX509Cert(self, ps, **kw):
165        '''Return Session Manager's X.509 certificate
166       
167        @type ps: ZSI ParsedSoap
168        @param ps: client SOAP message
169        @rtype: tuple
170        @return: request and response objects'''       
171        if self.__debug:
172                import pdb
173                pdb.set_trace()
174               
175        request, response = SessionMgrService.soap_getX509Cert(self, ps)
176
177        x509Cert = X509CertRead(srv.sm['certFile'])
178        response.X509Cert = base64.encodestring(x509Cert.asDER())
179        return request, response
180
181
182# Create Service
183srv = SessionMgrServiceSub()
184
185if srv.sm['useSignatureHandler']:
186        # Initialise WS-Security signature handler passing Attribute Authority
187        # public and private keys
188        caCertFile = srv.sm.get('caCertFile')
189        if caCertFile:
190                caCertFilePathList = (caCertFile,) 
191        else:
192                caCertFilePathList = None
193       
194        # Initialise WS-Security signature handler passing Session Manager
195        # public and private keys
196        WSSecurityHandler.signatureHandler = SignatureHandler(\
197                                                                verifyingCertFilePath=srv.sm['clntCertFile'],
198                                    signingCertFilePath=srv.sm['certFile'],
199                                    signingPriKeyFilePath=srv.sm['keyFile'],
200                                    signingPriKeyPwd=srv.sm['keyPwd'],
201                                    caCertFilePathList=caCertFilePathList)
202
203# Add Service to Session Manager branch
204root = Resource()
205root.putChild('SessionManager', srv)
206siteFactory = Site(root)
207
208if srv.sm['useSSL']:
209        # Use SSL connection
210#       from twisted.internet import ssl
211#       
212#       # Nb. ssl.DefaultOpenSSLContextFactory requires pyOpenSSL
213#       ctxFactory = ssl.DefaultOpenSSLContextFactory(srv.sm['sslKeyFile'],
214#                                                                                                 srv.sm['sslCertFile'])
215#       port = internet.SSLServer(srv.sm['portNum'], siteFactory, ctxFactory)
216
217    # Using M2Crypto ...
218    import os
219    os.putenv("OPENSSL_ALLOW_PROXY_CERTS", "1")
220
221    import twisted.protocols.policies as policies
222    from M2Crypto import SSL
223    from M2Crypto.SSL import TwistedProtocolWrapper
224    from M2Crypto.SSL.TwistedProtocolWrapper import TLSProtocolWrapper
225       
226    siteFactory.startTLS = True
227    siteFactory.sslChecker = SSL.Checker.Checker()
228
229        # TODO: Python ssl client seems to require SSL vers 2 is this a security
230        # risk?
231    ctx = SSL.Context(protocol='sslv23')
232    ctx.set_cipher_list("NULL-MD5:ALL:!ADH:!EXP:@STRENGTH")
233    ctx.load_cert(srv.sm['sslCertFile'], 
234                          srv.sm['sslKeyFile'],
235                          callback=lambda *args, **kw: srv.aa['sslKeyPwd'])
236                         
237    ctx.set_allow_unknown_ca(False)
238
239    # TODO: resolve check - verify_peer setting fails with
240    # BIOError: 'no certificate returned' error 18
241#    ctx.set_verify(SSL.verify_peer, 10)
242    ctx.set_verify(SSL.verify_client_once, 1)
243
244    ctx.load_verify_locations(cafile=os.path.basename(srv.sm['caCertFile']), 
245                                                  capath=os.path.dirname(srv.sm['caCertFile']))
246
247    class ContextFactory:
248        def getContext(self):
249            return ctx
250
251    factory = policies.WrappingFactory(siteFactory)
252    factory.protocol.TLS = True
253    factory.protocol = lambda factory, wrappedProtocol: \
254        TLSProtocolWrapper(factory,
255                           wrappedProtocol,
256                           startPassThrough=0,
257                           client=0,
258                           contextFactory=ContextFactory(),
259                           postConnectionCheck=None)
260
261    siteFactory = factory
262   
263    port = internet.TCPServer(srv.sm['portNum'], siteFactory)
264    port.CERTFILE = srv.sm['sslCertFile']
265    port.KEYFILE = srv.sm['sslKeyFile']
266    root.__class__.server = port
267else:   
268        # Non-SSL
269        port = internet.TCPServer(srv.sm['portNum'], siteFactory)
270
271application = service.Application("SessionManagerContainer")
272port.setServiceParent(application)
Note: See TracBrowser for help on using the repository browser.