source: TI12-security/trunk/python/ndg.security.server/ndg/security/server/zsi/twisted/attributeauthority/attAuthority.tac @ 4377

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.server/ndg/security/server/zsi/twisted/attributeauthority/attAuthority.tac@4377
Revision 4377, 10.8 KB checked in by pjkersha, 11 years ago (diff)

Renamed Attribute Authority classes and reran unittests

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