source: TI12-security/branches/ndg-security-1.5.x/ndg_security_server/ndg/security/server/wsgi/attributeauthority.py @ 7119

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/branches/ndg-security-1.5.x/ndg_security_server/ndg/security/server/wsgi/attributeauthority.py@7119
Revision 7119, 15.9 KB checked in by pjkersha, 10 years ago (diff)

Incomplete - task 10: OpenID Provider HTML/Javascript response incompatible with OpenID4Java

  • Removed old Session Manager code from 1.5.x branch
  • started updating certificates for new test CA.
  • Property svn:keywords set to Id
Line 
1"""WSGI Middleware to set an Attribute Authority instance in tyhe WSGI environ
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "19/08/09"
7__copyright__ = "(C) 2009 Science and Technology Facilities Council"
8__contact__ = "Philip.Kershaw@stfc.ac.uk"
9__license__ = "BSD - see LICENSE file in top-level directory"
10__revision__ = "$Id$"
11import logging
12log = logging.getLogger(__name__)
13import os
14
15from ndg.security.server.attributeauthority import AttributeAuthority
16from ndg.security.server.wsgi import NDGSecurityMiddlewareBase
17from ndg.security.server.wsgi.zsi import SOAPBindingMiddleware
18
19class AttributeAuthorityMiddleware(NDGSecurityMiddlewareBase):
20    '''WSGI to add an NDG Security Attribute Authority in the environ.  This
21    enables multiple WSGi filters to access the same underlying Attribute
22    Authority instance e.g. provide SAML SOAP and WSDL SOAP based interfaces
23    to the same Attribute Authority
24    '''
25    DEFAULT_KEYNAME = 'ndg.security.server.wsgi.attributeauthority'
26    ENVIRON_KEYNAME_CFG_OPTNAME = 'environKeyName'
27   
28    DEFAULT_ATTR_QUERY_IFACE_KEYNAME = \
29        'ndg.security.server.wsgi.attributeauthority.attributeQuery'
30    ENVIRON_KEYNAME_ATTR_QUERY_IFACE_CFG_OPT_NAME = \
31        'environKeyNameAttributeQueryInterface'
32       
33    def __init__(self, app):
34        '''Set-up an Attribute Authority instance
35        '''
36        # Stop in debugger at beginning of SOAP stub if environment variable
37        # is set
38        self.__debug = bool(os.environ.get('NDGSEC_INT_DEBUG'))
39        if self.__debug:
40            import pdb
41            pdb.set_trace()
42       
43        self._app = app
44        self.__aa = None
45        self.__attributeQuery = None
46        self.__keyName = None
47        self.__attributeQueryKeyName = None
48
49    def initialise(self, global_conf, prefix='attributeauthority.',
50                   **app_conf):
51        """Set-up Attribute authority middleware using a Paste app factory
52        pattern.  Overloaded base class method to enable custom settings from
53        app_conf
54       
55        @type app: callable following WSGI interface
56        @param app: next middleware application in the chain     
57        @type global_conf: dict       
58        @param global_conf: PasteDeploy global configuration dictionary
59        @type prefix: basestring
60        @param prefix: prefix for configuration items
61        @type app_conf: dict       
62        @param app_conf: PasteDeploy application specific configuration
63        dictionary
64        """
65        # Set key name for attribute authority set in environ
66        environKeyOptName = prefix + \
67                    AttributeAuthorityMiddleware.ENVIRON_KEYNAME_CFG_OPTNAME
68                   
69        self.keyName = app_conf.pop(environKeyOptName,
70                                AttributeAuthorityMiddleware.DEFAULT_KEYNAME)
71
72        attrQueryIfaceEnvironKeyOptName = prefix + \
73            AttributeAuthorityMiddleware.\
74            ENVIRON_KEYNAME_ATTR_QUERY_IFACE_CFG_OPT_NAME
75           
76        self.attributeQueryKeyName = app_conf.pop(
77            attrQueryIfaceEnvironKeyOptName,
78            AttributeAuthorityMiddleware.DEFAULT_ATTR_QUERY_IFACE_KEYNAME)
79       
80        self.aa = AttributeAuthority.fromProperties(propPrefix=prefix,
81                                                    **app_conf)
82        self.attributeQuery = self.aa.samlAttributeQueryFactory()
83
84    @classmethod
85    def filter_app_factory(cls, app, global_conf, **app_conf):
86        '''Wrapper to enable instantiation compatible with Paste Deploy
87        filter application factory function signature
88       
89        @type app: callable following WSGI interface
90        @param app: next middleware application in the chain     
91        @type global_conf: dict       
92        @param global_conf: PasteDeploy global configuration dictionary
93        @type prefix: basestring
94        @param prefix: prefix for configuration items
95        @type app_conf: dict       
96        @param app_conf: PasteDeploy application specific configuration
97        dictionary
98        '''
99        app = AttributeAuthorityMiddleware(app)
100        app.initialise(global_conf, **app_conf)
101       
102        return app
103   
104    def __call__(self, environ, start_response):
105        '''Set the Attribute Authority instantiated at initialisation in
106        environ
107       
108        @type environ: dict
109        @param environ: WSGI environment variables dictionary
110        @type start_response: function
111        @param start_response: standard WSGI start response function
112        @rtype: iterable
113        @return: next application in the WSGI stack
114        '''
115        environ[self.keyName] = self.aa
116        environ[self.attributeQueryKeyName] = self.attributeQuery
117        return self._app(environ, start_response)
118   
119    def _get_aa(self):
120        return self.__aa
121   
122    def _set_aa(self, val):
123        if not isinstance(val, AttributeAuthority):
124            raise TypeError('Expecting %r for "aa" attribute; got %r' %
125                            (AttributeAuthority, type(val)))
126        self.__aa = val
127           
128    aa = property(fget=_get_aa,
129                  fset=_set_aa,
130                  doc="Attribute Authority instance")
131
132    def _getKeyName(self):
133        return self.__keyName
134
135    def _setKeyName(self, val):
136        if not isinstance(val, basestring):
137            raise TypeError('Expecting %r for "keyName" attribute; got %r' %
138                            (basestring, type(val)))
139        self.__keyName = val
140       
141    keyName = property(fget=_getKeyName, 
142                       fset=_setKeyName, 
143                       doc="Key name used to index Attribute Authority in "
144                           "environ dictionary")
145
146    def _get_attributeQueryKeyName(self):
147        return self.__attributeQueryKeyName
148
149    def _set_attributeQueryKeyName(self, val):
150        if not isinstance(val, basestring):
151            raise TypeError('Expecting %r for "attributeQueryKeyName" '
152                            'attribute; got %r' % (basestring, type(val)))
153        self.__attributeQueryKeyName = val
154       
155    attributeQueryKeyName = property(fget=_get_attributeQueryKeyName, 
156                                     fset=_set_attributeQueryKeyName, 
157                                     doc="Key name used to index Attribute "
158                                         "Authority SAML attribute query "
159                                         "function in environ dictionary")
160   
161    def _get_attributeQuery(self):
162        return self.__attributeQuery
163
164    def _set_attributeQuery(self, val):
165        if not callable(val):
166            raise TypeError('Expecting a callable for "attributeQuery" '
167                            'attribute; got %r' % type(val))
168        self.__attributeQuery = val
169       
170    attributeQuery = property(fget=_get_attributeQuery, 
171                              fset=_set_attributeQuery, 
172                              doc="Attribute Authority SAML attribute query "
173                                  "function")
174
175
176from ndg.security.server.zsi.attributeauthority import AttributeAuthorityWS
177
178class AttributeAuthoritySOAPBindingMiddlewareConfigError(Exception):
179    """Raise if a configuration problem is found"""
180   
181   
182class AttributeAuthoritySOAPBindingMiddleware(NDGSecurityMiddlewareBase,
183                                              AttributeAuthorityWS):
184    """Inheritance from NDGSecurityMiddlewareBase provides a __call__
185    implementation which sets a reference to environ as an object attribute.
186   
187    Inheritance from AttributeAuthorityWS enables preservation of the same
188    SOAP callbacks but with the
189    ndg.security.server.attributeauthority.AttributeAuthority instance provided
190    from environ
191   
192    @type DEFAULT_ATTRIBUTE_AUTHORITY_ENVIRON_KEYNAME: basestring
193    @cvar DEFAULT_ATTRIBUTE_AUTHORITY_ENVIRON_KEYNAME: Key name used to index the
194    ndg.security.server.attributeauthority.AttributeAuthority instance in the
195    environ dictionary
196    @type ATTRIBUTE_AUTHORITY_ENVIRON_KEYNAME_CFG_OPTNAME: basestring
197    @cvar ATTRIBUTE_AUTHORITY_ENVIRON_KEYNAME_CFG_OPTNAME: configuration option name
198    for the attribute authority environ key
199    @type DEFAULT_ENVIRON_KEYNAME: basestring
200    @cvar DEFAULT_ENVIRON_KEYNAME: default value for Key name used to index
201    THIS SOAP Service Binding middleware instance in the environ dictionary
202    @type ENVIRON_KEYNAME_CFG_OPTNAME: basestring
203    @cvar ENVIRON_KEYNAME_CFG_OPTNAME: configuration option name for this
204    middleware's environ key
205    """
206    DEFAULT_ATTRIBUTE_AUTHORITY_ENVIRON_KEYNAME = \
207                "ndg.security.server.attributeauthority.AttributeAuthority"
208    ATTRIBUTE_AUTHORITY_ENVIRON_KEYNAME_CFG_OPTNAME = \
209                'attributeAuthorityEnvironKeyName'
210   
211    DEFAULT_ENVIRON_KEYNAME = ("ndg.security.server.wsgi.attributeauthority."
212                               "AttributeAuthoritySOAPBindingMiddleware")
213    ENVIRON_KEYNAME_CFG_OPTNAME = 'environKeyName'
214   
215    def __init__(self, app):
216        """Don't call AttributeAuthorityWS.__init__ - AttributeAuthority
217        instance is provided via environ through upstream
218        AttributeAuthorityMiddleware
219        """
220        # Call this base class initialiser to set-up the environ attribute
221        NDGSecurityMiddlewareBase.__init__(self, app, None)
222        AttributeAuthorityWS.__init__(self)
223       
224        self.__keyName = None
225        self.__attributeAuthorityKeyName = None
226       
227    def _getKeyName(self):
228        return self.__keyName
229
230    def _setKeyName(self, val):
231        if not isinstance(val, basestring):
232            raise TypeError('Expecting %r for "keyName" attribute; got %r' %
233                            (basestring, type(val)))
234        self.__keyName = val
235       
236    keyName = property(fget=_getKeyName, 
237                       fset=_setKeyName, 
238                       doc="Key name used to index THIS SOAP Service Binding "
239                           "middleware instance in the environ dictionary")   
240
241    def _getAttributeAuthorityKeyName(self):
242        return self.__attributeAuthorityKeyName
243
244    def _setAttributeAuthorityKeyName(self, val):
245        if not isinstance(val, basestring):
246            raise TypeError('Expecting %r for "attributeAuthorityKeyName" '
247                            'attribute; got %r' %(basestring, type(val)))
248        self.__attributeAuthorityKeyName = val
249       
250    attributeAuthorityKeyName = property(fget=_getAttributeAuthorityKeyName, 
251                                         fset=_setAttributeAuthorityKeyName, 
252                                         doc="Key name used to index the "
253                                             "ndg.security.server.attribute"
254                                             "authority.AttributeAuthority "
255                                             "instance in the environ "
256                                             "dictionary") 
257             
258    @classmethod
259    def filter_app_factory(cls, app, global_conf, 
260        attributeAuthoritySOAPBindingPrefix='attributeauthority.soapbinding.', 
261        **app_conf):
262        """Set-up Attribute Authority SOAP Binding middleware using a Paste app
263        factory pattern.  Overloaded base class method to enable custom
264        settings from app_conf
265       
266        @type app: callable following WSGI interface
267        @param app: next middleware application in the chain     
268        @type global_conf: dict       
269        @param global_conf: PasteDeploy global configuration dictionary
270        @type prefix: basestring
271        @param prefix: prefix for configuration items
272        @type app_conf: dict       
273        @param app_conf: PasteDeploy application specific configuration
274        dictionary
275        """
276        # Generic Binding middleware intercepts the SOAP_ACTION set in environ
277        # and maps it to the matching soap_{SOAP_ACTION} method from this class
278        soapBindingApp = SOAPBindingMiddleware.filter_app_factory(app, 
279                                                                  global_conf,
280                                                                  **app_conf)
281       
282        # Make the SOAP Binding wrapper pick up this Attribute Authority
283        # specific SOAP Binding
284        optName = attributeAuthoritySOAPBindingPrefix + \
285                cls.ENVIRON_KEYNAME_CFG_OPTNAME
286        soapBindingApp.serviceSOAPBindingKeyName = app_conf.get(optName,
287                                                cls.DEFAULT_ENVIRON_KEYNAME)
288       
289        # Instantiate this middleware and copy the environ key name setting for
290        # the Attribute Authority Service SOAP Binding
291        app = cls(soapBindingApp)
292        app.keyName = soapBindingApp.serviceSOAPBindingKeyName
293       
294        # envrion key name for the
295        # ndg.security.server.attributeauthority.AttributeAuthority instance
296        optName = attributeAuthoritySOAPBindingPrefix + \
297                cls.ATTRIBUTE_AUTHORITY_ENVIRON_KEYNAME_CFG_OPTNAME
298               
299        app.attributeAuthorityKeyName = app_conf.get(optName,
300                           cls.DEFAULT_ATTRIBUTE_AUTHORITY_ENVIRON_KEYNAME)
301
302           
303        # Extract local WS-Security signature verification filter
304        optName = attributeAuthoritySOAPBindingPrefix + \
305                            cls.WSSE_SIGNATURE_VERIFICATION_FILTER_ID_OPTNAME
306        app.wsseSignatureVerificationFilterID = app_conf.pop(optName, None)
307        if app.wsseSignatureVerificationFilterID is None:
308            log.warning('No "%s" option was set in the input config' % 
309                        cls.WSSE_SIGNATURE_VERIFICATION_FILTER_ID_OPTNAME)
310        else:   
311            log.info('Updated setting from "%s" option' % 
312                     cls.WSSE_SIGNATURE_VERIFICATION_FILTER_ID_OPTNAME)
313                   
314        return app
315 
316    @NDGSecurityMiddlewareBase.initCall
317    def __call__(self, environ, start_response):
318        """Set a reference to self in environ for the SOAPBindingMiddleware
319        instance to pick up downstream
320       
321        @type environ: dict
322        @param environ: WSGI environment variables dictionary
323        @type start_response: function
324        @param start_response: standard WSGI start response function
325        """
326
327        environ[self.keyName] = self
328        return self._app(environ, start_response)
329   
330    def soap_getAttCert(self, ps):
331        '''Retrieve an Attribute Certificate
332       
333        @type ps: ZSI ParsedSoap
334        @param ps: client SOAP message
335        @rtype: ndg.security.common.zsi.attributeauthority.AttributeAuthority_services_types.getAttCertResponse_Holder
336        @return: response'''
337        self._setAttributeAuthorityFromEnviron()
338        return AttributeAuthorityWS.soap_getAttCert(self, ps)
339
340    def soap_getHostInfo(self, ps):
341        '''Get information about this host
342               
343        @type ps: ZSI ParsedSoap
344        @param ps: client SOAP message
345        @rtype: response
346        @return: response'''
347        self._setAttributeAuthorityFromEnviron()
348        return AttributeAuthorityWS.soap_getHostInfo(self, ps)
349   
350    def soap_getAllHostsInfo(self, ps):
351        '''Get information about all hosts
352               
353        @type ps: ZSI ParsedSoap
354        @param ps: client SOAP message
355        @rtype: tuple
356        @return: response object'''
357        self._setAttributeAuthorityFromEnviron()
358        return AttributeAuthorityWS.soap_getAllHostsInfo(self, ps)
359   
360    def soap_getTrustedHostInfo(self, ps):
361        '''Get information about other trusted hosts
362               
363        @type ps: ZSI ParsedSoap
364        @param ps: client SOAP message
365        @rtype: tuple
366        @return: response object'''
367        self._setAttributeAuthorityFromEnviron()
368        return AttributeAuthorityWS.soap_getTrustedHostInfo(self, ps)
369   
370    def _setAttributeAuthorityFromEnviron(self):
371        self.aa = self.environ.get(self.attributeAuthorityKeyName)
372        if self.aa is None:
373            raise AttributeAuthoritySOAPBindingMiddlewareConfigError(
374                                            'No "%s" key found in environ' % 
375                                            self.attributeAuthorityKeyName)
Note: See TracBrowser for help on using the repository browser.