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

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

Working Attribute Authority unit tests with WS-Security multiple CAs support. This will be needed for deployment of MyProxy? with Simple CA at partner sites.

Added CA cert and certs and keys for a *TEST* CA for use with unit tests. This CA is NOT for production use.

python/ndg.security.server/setup.py: include .crt certs in conf/ package data

python/ndg.security.server/ndg/security/server/AttAuthority/init.py: added sslCACertDir param. It enables M2Crypto SSL server side to pick up multiple CA certs for a dir.

python/ndg.security.server/ndg/security/server/conf/certs/ca/init.py: make new ca/ dir a package so that it's exported with egg package data.

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

  • alter WS-Security SOAP handler init to accept multiple CA certs.
  • load multiple CA certs from sslCACertDir key of SessionMgr/AttAuthority? instance

python/ndg.security.server/ndg/security/server/conf/attAuthorityProperties.xml,
python/ndg.security.test/ndg/security/test/AttAuthority/siteBAttAuthorityProperties.xml,
python/ndg.security.test/ndg/security/test/sessionMgrClient/sessionMgrProperties.xml

  • added new sslCACertDir elem
  • fixed caCertFile - only single elem required

python/ndg.security.test/setup.py: include TEST CA and certs and keys issued from it for use in unit tests. These are fro test only.

python/ndg.security.test/ndg/security/test/AttAuthority/ca/ndg-test-ca.crt,
python/ndg.security.test/ndg/security/test/AttAuthority/siteA-aa.key,
python/ndg.security.test/ndg/security/test/AttAuthority/siteA-aa.crt: test CA certs and key.

python/ndg.security.test/ndg/security/test/AttAuthority/init.py: fix description

python/ndg.security.test/ndg/security/test/AttAuthority/AttAuthorityClientTest.py: ditto + added NDGSEC_INT_DEBUG env var option

python/ndg.security.test/ndg/security/test/AttAuthority/attAuthorityClientTest.cfg: fixed for new location of CA cert in ca/ sub-dir

python/ndg.security.test/ndg/security/test/sessionMgrClient/ca/init.py,
python/ndg.security.test/ndg/security/test/sessionMgr/ca/init.py,
python/ndg.security.test/ndg/security/test/AttAuthority/ca/init.py: ensure ca/ dir gets included in egg package data

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()
245
246if srv.aa['useSignatureHandler']:
247    # Initialise WS-Security signature handler passing Attribute Authority
248    # public and private keys
249    WSSecurityHandler.signatureHandler = SignatureHandler(\
250                                verifyingCertFilePath=srv.aa['clntCertFile'],
251                                signingCertFilePath=srv.aa['certFile'],
252                                signingPriKeyFilePath=srv.aa['keyFile'],
253                                signingPriKeyPwd=srv.aa['keyPwd'],
254                                caCertFilePathList=srv.aa.get('caCertFileList'))
255
256# Add Service to Attribute Authority branch
257root.putChild('AttributeAuthority', srv)
258siteFactory = Site(root)
259
260if srv.aa['useSSL']:
261        log.info("Running over https ...")
262
263        os.putenv("OPENSSL_ALLOW_PROXY_CERTS", "1")
264
265        import twisted.protocols.policies as policies
266
267        # Using M2Crypto
268        from M2Crypto import SSL
269        from M2Crypto.SSL import TwistedProtocolWrapper
270        from M2Crypto.SSL.TwistedProtocolWrapper import TLSProtocolWrapper
271
272        siteFactory.startTLS = True
273        siteFactory.sslChecker = SSL.Checker.Checker()
274       
275        # TODO: Python ssl client seems to require SSL vers 2 is this a security
276        # risk?
277        ctx = SSL.Context(protocol='sslv23')
278        ctx.set_cipher_list("NULL-MD5:ALL:!ADH:!EXP:@STRENGTH")
279        ctx.load_cert(srv.aa['sslCertFile'],
280                                  srv.aa['sslKeyFile'],
281                                  callback=lambda *args, **kw: srv.aa['sslKeyPwd'])
282                                 
283        ctx.set_allow_unknown_ca(False)
284       
285        # TODO: resolve check - verify_peer setting fails with
286        # BIOError: 'no certificate returned' error 18
287        #    ctx.set_verify(SSL.verify_peer, 10)
288        ctx.set_verify(SSL.verify_client_once, 1)
289       
290        ctx.load_verify_locations(capath=srv.aa['sslCACertDir'])
291       
292        class ContextFactory:
293            def getContext(self):
294                return ctx
295       
296        factory = policies.WrappingFactory(siteFactory)
297        factory.protocol.TLS = True
298        factory.protocol = lambda factory, wrappedProtocol: \
299            TLSProtocolWrapper(factory,
300                               wrappedProtocol,
301                               startPassThrough=0,
302                               client=0,
303                               contextFactory=ContextFactory(),
304                               postConnectionCheck=None)
305       
306        siteFactory = factory
307       
308        port = internet.TCPServer(srv.aa['portNum'], siteFactory)
309        port.CERTFILE = srv.aa['sslCertFile']
310        port.KEYFILE = srv.aa['sslKeyFile']
311        root.__class__.server = port
312else:   
313        # Non-SSL
314        log.info("Running over http ...")       
315        port = internet.TCPServer(srv.aa['portNum'], siteFactory)
316
317application = service.Application("AttributeAuthorityContainer")
318port.setServiceParent(application)
319       
Note: See TracBrowser for help on using the repository browser.