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

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

Major changes to enable trust based on multiple CAs and use of dynamically created user certs from MyProxy? SimpleCA - affects ...
python/ndg.security.server/ndg/security/server/AttAuthority/init.py,
python/ndg.security.test/ndg/security/test/AttAuthority/siteAAttAuthorityProperties.xml,
python/ndg.security.test/ndg/security/test/AttAuthority/siteBAttAuthorityProperties.xml,
python/ndg.security.server/ndg/security/server/conf/attAuthorityProperties.xml,
python/ndg.security.server/ndg/security/server/SessionMgr/init.py,
python/ndg.security.test/ndg/security/test/sessionMgrClient/sessionMgrProperties.xml,
python/ndg.security.server/ndg/security/server/conf/sessionMgrProperties.xml,
python/ndg.security.server/ndg/security/server/MyProxy.py,
python/ndg.security.test/ndg/security/test/sessionMgr/test.py,
python/ndg.security.common/ndg/security/common/CredWallet.py

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