source: TI12-security/trunk/python/ndg_security_server/ndg/security/server/wsgi/attributeauthority.py @ 5667

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg_security_server/ndg/security/server/wsgi/attributeauthority.py@5667
Revision 5667, 10.7 KB checked in by pjkersha, 11 years ago (diff)

Refactoring SOAPBindingMiddleware to accept a ZSI Service binding input from an upstream middleware component.

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.wsgi import NDGSecurityMiddlewareBase
16from ndg.security.server.attributeauthority import AttributeAuthority
17
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    @classmethod
50    def filter_app_factory(cls, app, global_conf, prefix='attributeauthority.',
51                           **app_conf):
52        """Set-up Attribute authority middleware using a Paste app factory
53        pattern.  Overloaded base class method to enable custom settings from
54        app_conf
55       
56        @type app: callable following WSGI interface
57        @param app: next middleware application in the chain     
58        @type global_conf: dict       
59        @param global_conf: PasteDeploy global configuration dictionary
60        @type prefix: basestring
61        @param prefix: prefix for configuration items
62        @type app_conf: dict       
63        @param app_conf: PasteDeploy application specific configuration
64        dictionary
65        """
66        app = AttributeAuthorityMiddleware(app)
67       
68        # Set key name for attribute authority set in environ
69        environKeyOptName = prefix + \
70                    AttributeAuthorityMiddleware.ENVIRON_KEYNAME_CFG_OPTNAME
71                   
72        app_conf.pop(environKeyOptName,
73                     AttributeAuthorityMiddleware.DEFAULT_KEYNAME)
74
75        attrQueryIfaceEnvironKeyOptName = prefix + \
76            AttributeAuthorityMiddleware.\
77            ENVIRON_KEYNAME_ATTR_QUERY_IFACE_CFG_OPT_NAME
78           
79        app.attributeQueryKeyName = app_conf.pop(
80            attrQueryIfaceEnvironKeyOptName,
81            AttributeAuthorityMiddleware.DEFAULT_ATTR_QUERY_IFACE_KEYNAME)
82       
83        app.aa = AttributeAuthority.fromProperties(propPrefix=prefix,
84                                                   **app_conf)
85        app.attributeQuery = app.aa.samlAttributeQueryFactory()
86       
87        return app
88       
89    def __call__(self, environ, start_response):
90        '''Set the Attribute Authority instantiated at initialisation in
91        environ
92       
93        @type environ: dict
94        @param environ: WSGI environment variables dictionary
95        @type start_response: function
96        @param start_response: standard WSGI start response function
97        @rtype: iterable
98        @return: next application in the WSGI stack
99        '''
100        environ[self.keyName] = self.aa
101        environ[self.attributeQueryKeyName] = self.attributeQuery
102        return self._app(environ, start_response)
103   
104    def _get_aa(self):
105        return self.__aa
106   
107    def _set_aa(self, val):
108        if not isinstance(val, AttributeAuthority):
109            raise TypeError('Expecting %r for "aa" attribute; got %r' %
110                            (AttributeAuthority, type(val)))
111        self.__aa = val
112           
113    aa = property(fget=_get_aa,
114                  fset=_set_aa,
115                  doc="Attribute Authority instance")
116
117    def _getKeyName(self):
118        return self.__keyName
119
120    def _setKeyName(self, val):
121        if not isinstance(val, basestring):
122            raise TypeError('Expecting %r for "keyName" attribute; got %r' %
123                            (basestring, type(val)))
124        self.__keyName = val
125       
126    keyName = property(fget=_getKeyName, 
127                       fset=_setKeyName, 
128                       doc="Key name used to index Attribute Authority in "
129                           "environ dictionary")
130
131    def _get_attributeQueryKeyName(self):
132        return self.__attributeQueryKeyName
133
134    def _set_attributeQueryKeyName(self, val):
135        if not isinstance(val, basestring):
136            raise TypeError('Expecting %r for "attributeQueryKeyName" '
137                            'attribute; got %r' % (basestring, type(val)))
138        self.__attributeQueryKeyName = val
139       
140    attributeQueryKeyName = property(fget=_get_attributeQueryKeyName, 
141                                     fset=_set_attributeQueryKeyName, 
142                                     doc="Key name used to index Attribute "
143                                         "Authority SAML attribute query "
144                                         "function in environ dictionary")
145   
146    def _get_attributeQuery(self):
147        return self.__attributeQuery
148
149    def _set_attributeQuery(self, val):
150        if not callable(val):
151            raise TypeError('Expecting a callable for "attributeQuery" '
152                            'attribute; got %r' % type(val))
153        self.__attributeQuery = val
154       
155    attributeQuery = property(fget=_get_attributeQuery, 
156                              fset=_set_attributeQuery, 
157                              doc="Attribute Authority SAML attribute query "
158                                  "function")
159
160
161from ndg.security.server.zsi.attributeauthority import AttributeAuthorityWS
162
163class AttributeAuthoritySOAPBindingMiddlewareConfigError(Exception):
164    """Raise if a configuration problem is found"""
165   
166   
167class AttributeAuthoritySOAPBindingMiddleware(NDGSecurityMiddlewareBase,
168                                              AttributeAuthorityWS):
169    """Inheritance from NDGSecurityMiddlewareBase provides a __call__
170    implementation which sets a reference to environ as an object attribute.
171   
172    Inheritance from AttributeAuthorityWS enables preservation of the same
173    SOAP callbacks but with the
174    ndg.security.server.attributeauthority.AttributeAuthority instance provided
175    from environ
176    """
177    DEFAULT_ATTRIBUTE_AUTHORITY_KEYNAME = \
178                "ndg.security.server.attributeauthority.AttributeAuthority"
179    ATTRIBUTE_AUTHORITY_KEYNAME_CFG_OPTNAME = 'attributeAuthorityEnvironKeyName'
180             
181    def __init__(self, app):
182        """Don't call AttributeAuthorityWS.__init__ - AttributeAuthority
183        instance is provided via environ through upstream
184        AttributeAuthorityMiddleware
185        """
186        # Call this base class initialiser to set-up the environ attribute
187        NDGSecurityMiddlewareBase.__init__(self, app, None)
188       
189        self.__keyName = None
190
191    def _getKeyName(self):
192        return self.__keyName
193
194    def _setKeyName(self, val):
195        if not isinstance(val, basestring):
196            raise TypeError('Expecting %r for "keyName" attribute; got %r' %
197                            (basestring, type(val)))
198        self.__keyName = val
199       
200    keyName = property(fget=_getKeyName, 
201                       fset=_setKeyName, 
202                       doc="Key name used to index Attribute Authority in "
203                           "environ dictionary")   
204         
205    @classmethod
206    def filter_app_factory(cls, app, global_conf, 
207                           prefix='attributeauthority.soapbinding.', 
208                           **app_conf):
209        """Set-up Attribute Authority SOAP Binding middleware using a Paste app
210        factory pattern.  Overloaded base class method to enable custom
211        settings from app_conf
212       
213        @type app: callable following WSGI interface
214        @param app: next middleware application in the chain     
215        @type global_conf: dict       
216        @param global_conf: PasteDeploy global configuration dictionary
217        @type prefix: basestring
218        @param prefix: prefix for configuration items
219        @type app_conf: dict       
220        @param app_conf: PasteDeploy application specific configuration
221        dictionary
222        """
223        app = cls(app)
224        app.keyName = app_conf.get(cls.ATTRIBUTE_AUTHORITY_KEYNAME_CFG_OPTNAME,
225                                   cls.DEFAULT_ATTRIBUTE_AUTHORITY_KEYNAME)
226        return app
227   
228    def soap_getAttCert(self, ps):
229        '''Retrieve an Attribute Certificate
230       
231        @type ps: ZSI ParsedSoap
232        @param ps: client SOAP message
233        @rtype: ndg.security.common.zsi.attributeauthority.AttributeAuthority_services_types.getAttCertResponse_Holder
234        @return: response'''
235        self._setAttributeAuthorityFromEnviron()
236        return AttributeAuthorityWS.soap_getAttCert(self, ps)
237
238    def soap_getHostInfo(self, ps):
239        '''Get information about this host
240               
241        @type ps: ZSI ParsedSoap
242        @param ps: client SOAP message
243        @rtype: response
244        @return: response'''
245        self._setAttributeAuthorityFromEnviron()
246        return AttributeAuthorityWS.soap_getHostInfo(self, ps)
247   
248    def soap_getAllHostsInfo(self, ps):
249        '''Get information about all hosts
250               
251        @type ps: ZSI ParsedSoap
252        @param ps: client SOAP message
253        @rtype: tuple
254        @return: response object'''
255        self._setAttributeAuthorityFromEnviron()
256        return AttributeAuthorityWS.soap_getAllHostsInfo(self, ps)
257   
258    def soap_getTrustedHostInfo(self, ps):
259        '''Get information about other trusted hosts
260               
261        @type ps: ZSI ParsedSoap
262        @param ps: client SOAP message
263        @rtype: tuple
264        @return: response object'''
265        self._setAttributeAuthorityFromEnviron()
266        return AttributeAuthorityWS.soap_getTrustedHostInfo(self, ps)
267   
268   
269    def _setAttributeAuthorityFromEnviron(self):
270        self.aa = self.environ.get(self.keyName)
271        if self.aa is None:
272            raise AttributeAuthoritySOAPBindingMiddlewareConfigError(
273                                'No "%s" key found in environ' % self.keyName)
Note: See TracBrowser for help on using the repository browser.