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

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.server/ndg/security/server/conf/attAuthority.tac@2884
Revision 2884, 8.0 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 Attribute Authority .tac file
3
4This file enables the Attribute Authority web service to be
5called under the Twisted framework
6
7NERC Data Grid Project
8
9@author P J Kershaw 17/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.AttAuthority.AttAuthority_services_server import \
24        AttAuthorityService
25
26from ndg.security.server.AttAuthority import AttAuthority, \
27        AttAuthorityAccessDenied
28       
29from ndg.security.common.wsSecurity import SignatureHandler
30from ndg.security.server.twisted import WSSecurityHandlerChainFactory, \
31        WSSecurityHandler
32
33from ndg.security.common.X509 import X509Cert, X509CertRead
34
35
36class AttAuthorityServiceSub(AttAuthorityService, WSResource):
37
38    # Add WS-Security handlers
39    factory = WSSecurityHandlerChainFactory
40
41    def __init__(self):
42        WSResource.__init__(self)
43         
44        # Initialize Attribute Authority class - property file will be
45        # picked up from default location under $NDG_DIR directory
46        self.aa = AttAuthority()
47       
48        # Stop in debugger at beginning of SOAP stub if environment variable
49        # is set
50        self.__debug = bool(os.environ.get('NDGSEC_INT_DEBUG'))
51
52
53    def soap_getAttCert(self, ps, **kw):
54        '''Retrieve an Attribute Certificate
55       
56        @type ps: ZSI ParsedSoap
57        @param ps: client SOAP message
58        @rtype: tuple
59        @return: request and response objects'''
60        if self.__debug:
61                import pdb
62                pdb.set_trace()
63               
64        request, response = AttAuthorityService.soap_getAttCert(self, ps)
65
66        # Derive designated holder cert differently according to whether
67        # a signed message is expected from the client
68        if srv.aa['useSignatureHandler']:
69            # Get certificate corresponding to private key that signed the
70            # message - i.e. the user's proxy
71            holderCert = WSSecurityHandler.signatureHandler.verifyingCert
72        else:
73            # No signature from client - they must instead provide the
74            # designated holder cert via the UserCert input
75            holderCert = request.UserCert
76
77        try:   
78                attCert = self.aa.getAttCert(userId=request.UserId,
79                                         holderCert=holderCert,
80                                         userAttCert=request.UserAttCert) 
81                response.AttCert = attCert.toString()
82               
83        except AttAuthorityAccessDenied, e:
84            response.Msg = str(e)
85                       
86        return request, response
87
88
89    def soap_getHostInfo(self, ps, **kw):
90        '''Get information about this host
91               
92        @type ps: ZSI ParsedSoap
93        @param ps: client SOAP message
94        @rtype: tuple
95        @return: request and response objects'''
96        if self.__debug:
97                import pdb
98                pdb.set_trace()
99               
100        request, response = AttAuthorityService.soap_getHostInfo(self, ps)
101       
102        response.Hostname = srv.aa.hostInfo.keys()[0]
103        response.LoginURI = srv.aa.hostInfo[response.Hostname]['loginURI']
104        response.AaURI = srv.aa.hostInfo[response.Hostname]['aaURI']
105
106        return request, response
107
108
109    def soap_getTrustedHostInfo(self, ps, **kw):
110        '''Get information about other trusted hosts
111               
112        @type ps: ZSI ParsedSoap
113        @param ps: client SOAP message
114        @rtype: tuple
115        @return: request and response objects'''
116        if self.__debug:
117                import pdb
118                pdb.set_trace()
119               
120        request, response = \
121                        AttAuthorityService.soap_getTrustedHostInfo(self, ps)
122       
123        trustedHostInfo = srv.aa.getTrustedHostInfo(role=request.Role)
124
125                # Convert ready for serialization
126        trustedHosts = []
127        for hostname, hostInfo in trustedHostInfo.items():
128            trustedHost = response.new_trustedHosts()
129                       
130            trustedHost.Hostname = hostname
131            trustedHost.AaURI = hostInfo['aaURI']
132            trustedHost.LoginURI = hostInfo['loginURI']
133            trustedHost.RoleList = hostInfo['role']
134                       
135            trustedHosts.append(trustedHost)
136                       
137        response.TrustedHosts = trustedHosts
138               
139        return request, response
140
141
142    def soap_getX509Cert(self, ps, **kw):
143        '''Retrieve Attribute Authority's X.509 certificate
144       
145        @type ps: ZSI ParsedSoap
146        @param ps: client SOAP message
147        @rtype: tuple
148        @return: request and response objects'''
149        if self.__debug:
150                import pdb
151                pdb.set_trace()
152               
153        request, response = AttAuthorityService.soap_getX509Cert(self, ps)
154       
155        x509Cert = X509CertRead(srv.aa['certFile'])
156        response.X509Cert = base64.encodestring(x509Cert.asDER())
157        return request, response
158
159
160root = Resource()
161
162# Create Service
163srv = AttAuthorityServiceSub()
164
165if srv.aa['useSignatureHandler']:
166    # Initialise WS-Security signature handler passing Attribute Authority
167    # public and private keys
168    caCertFile = srv.aa.get('caCertFile')
169    if caCertFile:
170        caCertFilePathList = (caCertFile,) 
171    else:
172                caCertFilePathList = None
173   
174    WSSecurityHandler.signatureHandler = SignatureHandler(\
175                                verifyingCertFilePath=srv.aa['clntCertFile'],
176                                signingCertFilePath=srv.aa['certFile'],
177                                signingPriKeyFilePath=srv.aa['keyFile'],
178                                signingPriKeyPwd=srv.aa['keyPwd'],
179                                caCertFilePathList=caCertFilePathList)
180
181# Add Service to Attribute Authority branch
182root.putChild('AttributeAuthority', srv)
183siteFactory = Site(root)
184
185if srv.aa['useSSL']:
186        # Use SSL connection
187#       from twisted.internet import ssl
188#       
189#       # Nb. ssl.DefaultOpenSSLContextFactory requires pyOpenSSL
190#       ctxFactory = ssl.DefaultOpenSSLContextFactory(srv.aa['sslKeyFile'],
191#                                                                                                 srv.aa['sslCertFile'])
192#       port = internet.SSLServer(srv.aa['portNum'], siteFactory, ctxFactory)
193
194        # Using M2Crypto ...
195    os.putenv("OPENSSL_ALLOW_PROXY_CERTS", "1")
196
197    import twisted.protocols.policies as policies
198    from M2Crypto import SSL
199    from M2Crypto.SSL import TwistedProtocolWrapper
200    from M2Crypto.SSL.TwistedProtocolWrapper import TLSProtocolWrapper
201
202    siteFactory.startTLS = True
203    siteFactory.sslChecker = SSL.Checker.Checker()
204
205        # TODO: Python ssl client seems to require SSL vers 2 is this a security
206        # risk?
207    ctx = SSL.Context(protocol='sslv23')
208    ctx.set_cipher_list("NULL-MD5:ALL:!ADH:!EXP:@STRENGTH")
209    ctx.load_cert(srv.aa['sslCertFile'], 
210                          srv.aa['sslKeyFile'],
211                          callback=lambda *args, **kw: srv.aa['sslKeyPwd'])
212                         
213    ctx.set_allow_unknown_ca(False)
214
215    # TODO: resolve check - verify_peer setting fails with
216    # BIOError: 'no certificate returned' error 18
217#    ctx.set_verify(SSL.verify_peer, 10)
218    ctx.set_verify(SSL.verify_client_once, 1)
219
220    ctx.load_verify_locations(cafile=os.path.basename(srv.aa['caCertFile']), 
221                                                  capath=os.path.dirname(srv.aa['caCertFile']))
222
223    class ContextFactory:
224        def getContext(self):
225            return ctx
226
227    factory = policies.WrappingFactory(siteFactory)
228    factory.protocol.TLS = True
229    factory.protocol = lambda factory, wrappedProtocol: \
230        TLSProtocolWrapper(factory,
231                           wrappedProtocol,
232                           startPassThrough=0,
233                           client=0,
234                           contextFactory=ContextFactory(),
235                           postConnectionCheck=None)
236
237    siteFactory = factory
238   
239    port = internet.TCPServer(srv.aa['portNum'], siteFactory)
240    port.CERTFILE = srv.aa['sslCertFile']
241    port.KEYFILE = srv.aa['sslKeyFile']
242    root.__class__.server = port
243else:   
244        # Non-SSL
245        port = internet.TCPServer(srv.aa['portNum'], siteFactory)
246
247application = service.Application("AttributeAuthorityContainer")
248port.setServiceParent(application)
249       
Note: See TracBrowser for help on using the repository browser.