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

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.server/ndg/security/server/conf/attAuthority.tac@4110
Revision 4110, 10.6 KB checked in by cbyrom, 11 years ago (diff)

Allow BinarySecurityToken? ValueType? and whether SignatureConfirmation?
is required to be set from server xml properties file.

Line 
1"""NDG Security Attribute Authority .tac file
2
3This file enables the Attribute Authority web service to be
4called under the Twisted framework
5
6NERC Data Grid Project
7"""
8__author__ = "P J Kershaw"
9__date__ = "17/11/06"
10__copyright__ = "(C) 2007 STFC & NERC"
11__license__ = \
12"""This software may be distributed under the terms of the Q Public
13License, version 1.0 or later."""
14__contact__ = "P.J.Kershaw@rl.ac.uk"
15__revision__ = '$Id$'
16
17import os, base64
18from logging.config import fileConfig
19try:
20        _logConfig = os.path.join(os.environ["NDGSEC_DIR"],
21                                                          'conf',
22                                                          'attAuthorityLog.cfg')
23        fileConfig(_logConfig)
24except KeyError:
25        from warnings import warn
26        warn(\
27        '"NDGSEC_DIR" environment variable must be set to enable logging config',
28        RuntimeWarning)
29       
30import logging
31log = logging.getLogger(__name__)
32
33from ZSI.twisted.WSresource import WSResource
34from twisted.application import service, internet
35from twisted.web.server import Site
36from twisted.web.resource import Resource
37
38from ndg.security.server.AttAuthority.AttAuthority_services_server import \
39        AttAuthorityService
40
41from ndg.security.server.AttAuthority import AttAuthority, \
42        AttAuthorityAccessDenied
43       
44from ndg.security.common.wsSecurity import SignatureHandler
45from ndg.security.server.twisted import WSSecurityHandlerChainFactory, \
46        WSSecurityHandler
47
48from ndg.security.common.X509 import X509Cert, X509CertRead
49
50
51class AttAuthorityServiceSub(AttAuthorityService, WSResource):
52
53    # Add WS-Security handlers
54    factory = WSSecurityHandlerChainFactory
55
56    def __init__(self):
57       
58        # Stop in debugger at beginning of SOAP stub if environment variable
59        # is set
60        self.__debug = bool(os.environ.get('NDGSEC_INT_DEBUG'))
61        if self.__debug:
62                import pdb
63                pdb.set_trace()
64               
65        WSResource.__init__(self)
66         
67        # Initialize Attribute Authority class - property file will be
68        # picked up from default location under $NDG_DIR directory
69        self.aa = AttAuthority()
70
71
72    def soap_getAttCert(self, ps, **kw):
73        '''Retrieve an Attribute Certificate
74       
75        @type ps: ZSI ParsedSoap
76        @param ps: client SOAP message
77        @rtype: tuple
78        @return: request and response objects'''
79        if self.__debug:
80                import pdb
81                pdb.set_trace()
82               
83        request, response = AttAuthorityService.soap_getAttCert(self, ps)
84
85        # Derive designated holder cert differently according to whether
86        # a signed message is expected from the client
87        if srv.aa['useSignatureHandler']:
88            # Get certificate corresponding to private key that signed the
89            # message - i.e. the user's proxy
90            holderCert = WSSecurityHandler.signatureHandler.verifyingCert
91        else:
92            # No signature from client - they must instead provide the
93            # designated holder cert via the UserCert input
94            holderCert = request.UserCert
95
96        try:   
97                attCert = self.aa.getAttCert(userId=request.UserId,
98                                         holderCert=holderCert,
99                                         userAttCert=request.UserAttCert) 
100                response.AttCert = attCert.toString()
101               
102        except AttAuthorityAccessDenied, e:
103            response.Msg = str(e)
104                       
105        return request, response
106       
107
108    def soap_getHostInfo(self, ps, **kw):
109        '''Get information about this host
110               
111        @type ps: ZSI ParsedSoap
112        @param ps: client SOAP message
113        @rtype: tuple
114        @return: request and response objects'''
115        if self.__debug:
116                import pdb
117                pdb.set_trace()
118               
119        request, response = AttAuthorityService.soap_getHostInfo(self, ps)
120       
121        response.Hostname = srv.aa.hostInfo.keys()[0]
122        response.AaURI = srv.aa.hostInfo[response.Hostname]['aaURI']
123        response.AaDN = srv.aa.hostInfo[response.Hostname]['aaDN']
124        response.LoginURI = srv.aa.hostInfo[response.Hostname]['loginURI']
125        response.LoginServerDN = \
126                srv.aa.hostInfo[response.Hostname]['loginServerDN']
127        response.LoginRequestServerDN = \
128                srv.aa.hostInfo[response.Hostname]['loginRequestServerDN']
129
130        return request, response
131       
132
133    def soap_getAllHostsInfo(self, ps, **kw):
134        '''Get information about all hosts
135               
136        @type ps: ZSI ParsedSoap
137        @param ps: client SOAP message
138        @rtype: tuple
139        @return: request and response objects'''
140        if self.__debug:
141                import pdb
142                pdb.set_trace()
143               
144        request, response = AttAuthorityService.soap_getAllHostsInfo(self, ps)
145       
146
147        trustedHostInfo = srv.aa.getTrustedHostInfo()
148
149                # Convert ready for serialization
150               
151                # First get info for THIS Attribute Authority ...
152                # Nb. No role lsit applies here
153        hosts = [response.new_hosts()]
154       
155        hosts[0].Hostname = srv.aa.hostInfo.keys()[0]
156       
157        hosts[0].AaURI = \
158                srv.aa.hostInfo[hosts[0].Hostname]['aaURI']
159        hosts[0].AaDN = \
160                srv.aa.hostInfo[hosts[0].Hostname]['aaDN']
161
162        hosts[0].LoginURI = srv.aa.hostInfo[hosts[0].Hostname]['loginURI']
163        hosts[0].LoginServerDN = \
164                srv.aa.hostInfo[hosts[0].Hostname]['loginServerDN']
165        hosts[0].LoginRequestServerDN = \
166                srv.aa.hostInfo[hosts[0].Hostname]['loginRequestServerDN']
167       
168                # ... then append info for other trusted attribute authorities...
169        for hostname, hostInfo in trustedHostInfo.items():
170            host = response.new_hosts()
171                       
172            host.Hostname = hostname
173            host.AaURI = hostInfo['aaURI']
174            host.AaDN = hostInfo['aaDN']
175            host.LoginURI = hostInfo['loginURI']
176            host.LoginServerDN = hostInfo['loginServerDN']
177            host.LoginRequestServerDN=hostInfo['loginRequestServerDN']
178            host.RoleList = hostInfo['role']
179                       
180            hosts.append(host)
181                       
182        response.Hosts = hosts
183
184        return request, response
185
186
187    def soap_getTrustedHostInfo(self, ps, **kw):
188        '''Get information about other trusted hosts
189               
190        @type ps: ZSI ParsedSoap
191        @param ps: client SOAP message
192        @rtype: tuple
193        @return: request and response objects'''
194        if self.__debug:
195                import pdb
196                pdb.set_trace()
197               
198        request, response = \
199                        AttAuthorityService.soap_getTrustedHostInfo(self, ps)
200       
201        trustedHostInfo = srv.aa.getTrustedHostInfo(role=request.Role)
202
203                # Convert ready for serialization
204        trustedHosts = []
205        for hostname, hostInfo in trustedHostInfo.items():
206            trustedHost = response.new_trustedHosts()
207                       
208            trustedHost.Hostname = hostname
209            trustedHost.AaURI = hostInfo['aaURI']
210            trustedHost.AaDN = hostInfo['aaDN']
211            trustedHost.LoginURI = hostInfo['loginURI']
212            trustedHost.LoginServerDN = hostInfo['loginServerDN']
213            trustedHost.LoginRequestServerDN=hostInfo['loginRequestServerDN']
214            trustedHost.RoleList = hostInfo['role']
215                       
216            trustedHosts.append(trustedHost)
217                       
218        response.TrustedHosts = trustedHosts
219               
220        return request, response
221
222
223    def soap_getX509Cert(self, ps, **kw):
224        '''Retrieve Attribute Authority's X.509 certificate
225       
226        @type ps: ZSI ParsedSoap
227        @param ps: client SOAP message
228        @rtype: tuple
229        @return: request and response objects'''
230        if self.__debug:
231                import pdb
232                pdb.set_trace()
233               
234        request, response = AttAuthorityService.soap_getX509Cert(self, ps)
235       
236        x509Cert = X509CertRead(srv.aa['certFile'])
237        response.X509Cert = base64.encodestring(x509Cert.asDER())
238        return request, response
239
240
241root = Resource()
242
243# Create Service
244srv = AttAuthorityServiceSub()
245if srv.aa['useSignatureHandler']:
246    # Initialise WS-Security signature handler passing Attribute Authority
247    # public and private keys
248   
249    # Inclusive namespaces for Exclusive C14N
250    refC14nKw = {'unsuppressedPrefixes': srv.aa['wssRefInclNS']}
251    signedInfoC14nKw = {'unsuppressedPrefixes':
252                        srv.aa['wssSignedInfoInclNS']}
253   
254    WSSecurityHandler.signatureHandler = SignatureHandler(\
255                                        verifyingCertFilePath=srv.aa['clntCertFile'],
256                                        signingCertFilePath=srv.aa['certFile'],
257                                        signingPriKeyFilePath=srv.aa['keyFile'],
258                                        signingPriKeyPwd=srv.aa['keyPwd'],
259                                        caCertFilePathList=srv.aa.get('caCertFileList'),
260                                        refC14nKw=refC14nKw,
261                                        signedInfoC14nKw=signedInfoC14nKw,
262                                        reqBinSecTokValType=srv.aa.get('reqBinSecTokValType'),
263                                        applySignatureConfirmation=srv.aa.get('applySignatureConfirmation'))
264
265# Add Service to Attribute Authority branch
266root.putChild('AttributeAuthority', srv)
267siteFactory = Site(root)
268if srv.aa['useSSL']:
269        log.info("Running over https ...")
270
271        os.putenv("OPENSSL_ALLOW_PROXY_CERTS", "1")
272
273        import twisted.protocols.policies as policies
274
275        # Using M2Crypto
276        from M2Crypto import SSL
277        from M2Crypto.SSL import TwistedProtocolWrapper
278        from M2Crypto.SSL.TwistedProtocolWrapper import TLSProtocolWrapper
279
280        siteFactory.startTLS = True
281        siteFactory.sslChecker = SSL.Checker.Checker()
282       
283        # TODO: Python ssl client seems to require SSL vers 2 is this a security
284        # risk?
285        ctx = SSL.Context(protocol='sslv23')
286        ctx.set_cipher_list("NULL-MD5:ALL:!ADH:!EXP:@STRENGTH")
287        ctx.load_cert(srv.aa['sslCertFile'],
288                                  srv.aa['sslKeyFile'],
289                                  callback=lambda *args, **kw: srv.aa['sslKeyPwd'])
290                                 
291        ctx.set_allow_unknown_ca(False)
292       
293        # TODO: resolve check - verify_peer setting fails with
294        # BIOError: 'no certificate returned' error 18
295        #    ctx.set_verify(SSL.verify_peer, 10)
296        ctx.set_verify(SSL.verify_client_once, 1)
297       
298        ctx.load_verify_locations(capath=srv.aa['sslCACertDir'])
299       
300        class ContextFactory:
301            def getContext(self):
302                return ctx
303       
304        factory = policies.WrappingFactory(siteFactory)
305        factory.protocol.TLS = True
306        factory.protocol = lambda factory, wrappedProtocol: \
307            TLSProtocolWrapper(factory,
308                               wrappedProtocol,
309                               startPassThrough=0,
310                               client=0,
311                               contextFactory=ContextFactory(),
312                               postConnectionCheck=None)
313       
314        siteFactory = factory
315       
316        port = internet.TCPServer(srv.aa['portNum'], siteFactory)
317        port.CERTFILE = srv.aa['sslCertFile']
318        port.KEYFILE = srv.aa['sslKeyFile']
319        root.__class__.server = port
320else:   
321        # Non-SSL
322        log.info("Running over http ...")       
323        port = internet.TCPServer(srv.aa['portNum'], siteFactory)
324
325application = service.Application("AttributeAuthorityContainer")
326port.setServiceParent(application)
327       
Note: See TracBrowser for help on using the repository browser.