source: TI12-security/trunk/python/ndg.security.server/ndg/security/server/AttAuthority/server-config.tac @ 2855

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

Fixes to tickets #828 #829

ndg.security.server/ndg/security/server/AttAuthority/server-config.tac,
ndg.security.server/ndg/security/server/ca/server-config.tac,
ndg.security.server/ndg/security/server/SessionMgr/server-config.tac:

  • Split import for wsSecurity into common component (no Zope or Twisted) and

server component (Zope and Twisted imports)

ndg.security.server/ndg/security/server/twisted.py:

  • new module to contain Twisted handler code for NDG-Security server egg.

This code is removed from common.wsSecurity so that the client egg no longer
has any Twisted or Zope dependencies

ndg.security.common/ndg/security/common/wsSecurity.py: removed Twisted handler
code and moved to new server.twisted module

ndg-security-install.py: add new --config-dir option to copy server egg conf/
dir contents to /etc/ndg/security on target host. Incomplete as a way to
programmatically get the egg site-packages/ location is needed.

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
49    def soap_getAttCert(self, ps, **kw):
50        request, response = AttAuthorityService.soap_getAttCert(self, ps)
51
52        # Derive designated holder cert differently according to whether
53        # a signed message is expected from the client
54        if srv.aa['useSignatureHandler']:
55            # Get certificate corresponding to private key that signed the
56            # message - i.e. the user's proxy
57            holderCert = WSSecurityHandler.signatureHandler.verifyingCert
58        else:
59            # No signature from client - they must instead provide the
60            # designated holder cert via the UserCert input
61            holderCert = request.UserCert
62
63        try:   
64                attCert = self.aa.getAttCert(userId=request.UserId,
65                                         holderCert=holderCert,
66                                         userAttCert=request.UserAttCert) 
67                response.AttCert = attCert.toString()
68               
69        except AttAuthorityAccessDenied, e:
70            response.Msg = str(e)
71                       
72        return request, response
73
74
75    def soap_getHostInfo(self, ps, **kw):
76        request, response = AttAuthorityService.soap_getHostInfo(self, ps)
77       
78        response.Hostname = srv.aa.hostInfo.keys()[0]
79        response.LoginURI = srv.aa.hostInfo[response.Hostname]['loginURI']
80        response.AaURI = srv.aa.hostInfo[response.Hostname]['aaURI']
81
82        return request, response
83
84
85    def soap_getTrustedHostInfo(self, ps, **kw):
86        request, response = \
87                        AttAuthorityService.soap_getTrustedHostInfo(self, ps)
88       
89        trustedHostInfo = srv.aa.getTrustedHostInfo(role=request.Role)
90
91                # Convert ready for serialization
92        trustedHosts = []
93        for hostname, hostInfo in trustedHostInfo.items():
94            trustedHost = response.new_trustedHosts()
95                       
96            trustedHost.Hostname = hostname
97            trustedHost.AaURI = hostInfo['aaURI']
98            trustedHost.LoginURI = hostInfo['loginURI']
99            trustedHost.RoleList = hostInfo['role']
100                       
101            trustedHosts.append(trustedHost)
102                       
103        response.TrustedHosts = trustedHosts
104               
105        return request, response
106
107
108    def soap_getX509Cert(self, ps, **kw):
109        '''Retrieve Attribute Authority's X.509 certificate'''
110        request, response = AttAuthorityService.soap_getX509Cert(self, ps)
111       
112        x509Cert = X509CertRead(srv.aa['certFile'])
113        response.X509Cert = base64.encodestring(x509Cert.asDER())
114        return request, response
115
116
117root = Resource()
118
119# Create Service
120srv = AttAuthorityServiceSub()
121
122if srv.aa['useSignatureHandler']:
123    # Initialise WS-Security signature handler passing Attribute Authority
124    # public and private keys
125    caCertFile = srv.aa.get('caCertFile')
126    if caCertFile:
127        caCertFilePathList = (caCertFile,) 
128    else:
129                caCertFilePathList = None
130   
131    WSSecurityHandler.signatureHandler = SignatureHandler(\
132                                verifyingCertFilePath=srv.aa['clntCertFile'],
133                                signingCertFilePath=srv.aa['certFile'],
134                                signingPriKeyFilePath=srv.aa['keyFile'],
135                                signingPriKeyPwd=srv.aa['keyPwd'],
136                                caCertFilePathList=caCertFilePathList)
137
138# Add Service to Attribute Authority branch
139root.putChild('AttributeAuthority', srv)
140siteFactory = Site(root)
141
142if srv.aa['useSSL']:
143        # Use SSL connection
144#       from twisted.internet import ssl
145#       
146#       # Nb. ssl.DefaultOpenSSLContextFactory requires pyOpenSSL
147#       ctxFactory = ssl.DefaultOpenSSLContextFactory(srv.aa['sslKeyFile'],
148#                                                                                                 srv.aa['sslCertFile'])
149#       port = internet.SSLServer(srv.aa['portNum'], siteFactory, ctxFactory)
150
151        # Using M2Crypto ...
152    os.putenv("OPENSSL_ALLOW_PROXY_CERTS", "1")
153
154    import twisted.protocols.policies as policies
155    from M2Crypto import SSL
156    from M2Crypto.SSL import TwistedProtocolWrapper
157    from M2Crypto.SSL.TwistedProtocolWrapper import TLSProtocolWrapper
158
159    siteFactory.startTLS = True
160    siteFactory.sslChecker = SSL.Checker.Checker()
161
162        # TODO: Python ssl client seems to require SSL vers 2 is this a security
163        # risk?
164    ctx = SSL.Context(protocol='sslv23')
165    ctx.set_cipher_list("NULL-MD5:ALL:!ADH:!EXP:@STRENGTH")
166    ctx.load_cert(srv.aa['sslCertFile'], 
167                          srv.aa['sslKeyFile'],
168                          callback=lambda *args, **kw: srv.aa['sslKeyPwd'])
169                         
170    ctx.set_allow_unknown_ca(False)
171
172    # TODO: resolve check - verify_peer setting fails with
173    # BIOError: 'no certificate returned' error 18
174#    ctx.set_verify(SSL.verify_peer, 10)
175    ctx.set_verify(SSL.verify_client_once, 1)
176
177    ctx.load_verify_locations(cafile=os.path.basename(srv.aa['caCertFile']), 
178                                                  capath=os.path.dirname(srv.aa['caCertFile']))
179
180    class ContextFactory:
181        def getContext(self):
182            return ctx
183
184    factory = policies.WrappingFactory(siteFactory)
185    factory.protocol.TLS = True
186    factory.protocol = lambda factory, wrappedProtocol: \
187        TLSProtocolWrapper(factory,
188                           wrappedProtocol,
189                           startPassThrough=0,
190                           client=0,
191                           contextFactory=ContextFactory(),
192                           postConnectionCheck=None)
193
194    siteFactory = factory
195   
196    port = internet.TCPServer(srv.aa['portNum'], siteFactory)
197    port.CERTFILE = srv.aa['sslCertFile']
198    port.KEYFILE = srv.aa['sslKeyFile']
199    root.__class__.server = port
200else:   
201        # Non-SSL
202        port = internet.TCPServer(srv.aa['portNum'], siteFactory)
203
204application = service.Application("AttributeAuthorityContainer")
205port.setServiceParent(application)
206       
Note: See TracBrowser for help on using the repository browser.