Changeset 4909


Ignore:
Timestamp:
06/02/09 16:56:59 (11 years ago)
Author:
pjkersha
Message:

Major progress on authentication and authorisation WSGI chain:

  • integration test harness in ndg.security.test.integration.authz
    • chain PEP middleware catches secured URIs. If URI is a secured one, it sets the status to 403.
    • The 403 status is caught by the PDP. The PDP checks for a login cookie, if not set it sets 401 Unauthorized
    • 401 is caught by OpenID handler and sets OpenID signin form response so that the user can login
    • If the user is logged in, the PDP checks authZ credentials (TODO) if not set it sets a 403 status and responds with an access denied message
  • The PDP uses authkit.authenticate.multi.MultiHandler? to trap 403 responses from the PEP and display an access denied message.
  • ndg.security.server.wsgi.pdp needs cleaning up in line with change to use authkit MultiHandler?
Location:
TI12-security/trunk/python
Files:
29 added
6 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/__init__.py

    r4907 r4909  
    1212import httplib 
    1313 
    14  
     14class NDGSecurityMiddlewareError(Exception): 
     15    '''Base exception class for NDG Security middleware''' 
     16     
     17class NDGSecurityMiddlewareConfigError(NDGSecurityMiddlewareError): 
     18    '''NDG Security Middleware Configuration error''' 
     19     
    1520class NDGSecurityMiddlewareBase(object): 
    1621    """Base class for NDG Security Middleware classes""" 
     
    109114        return response 
    110115         
     116    @staticmethod 
     117    def getStatusMessage(statusCode): 
     118        '''Make a standard status message for use with start_response 
     119        @type statusCode: int 
     120        @param statusCode: HTTP status code 
     121        @rtype: str 
     122        @return: status code with standard message 
     123        @raise KeyError: for invalid status code 
     124        ''' 
     125        return '%d %s' % (statusCode, httplib.responses[statusCode]) 
     126     
    111127    # Utility functions to support Paste Deploy application and filter function 
    112128    # signatures 
     
    235251                              fset=_setStart_response, 
    236252                              doc="Reference to WSGI start_response function") 
    237      
     253         
     254         
     255    def _redirect(self, url, start_response=None): 
     256        """Do a HTTP 302 redirect 
     257         
     258        @type start_response: callable following WSGI start_response convention 
     259        @param start_response: WSGI start response callable 
     260        @type url: basestring 
     261        @param url: URL to redirect to 
     262        @rtype: list 
     263        @return: empty HTML body 
     264        """ 
     265        if start_response is None: 
     266            # self.start_response will be None if initCall decorator wasn't  
     267            # applied to __call__ 
     268            if start_response is None: 
     269                raise NDGSecurityMiddlewareConfigError("No start_response " 
     270                                                       "function set.") 
     271            start_response = self.start_response 
     272             
     273        start_response(NDGSecurityMiddlewareBase.getStatusMessage(302),  
     274                       [('Content-type', 'text/html'), 
     275                        ('Content-length', '0'), 
     276                        ('Location', url)]) 
     277        return [] 
     278    
     279    
    238280class NDGSecurityPathFilter(NDGSecurityMiddlewareBase): 
    239     """Specialization of NDG Security Middleware to enable filtering based on 
     281    """Specialisation of NDG Security Middleware to enable filtering based on 
    240282    PATH_INFO 
    241283     
     
    259301 
    260302    _isSSLRequest = lambda self: self.environ.get( 
    261                                 NDGSecurityPathFilter.sslKeyName) == '1' 
     303                                    NDGSecurityPathFilter.sslKeyName) == '1' 
    262304    isSSLRequest = property(fget=_isSSLRequest, 
    263                             doc="Approximation for is an SSL request boolean " 
    264                                 "- depends on Apache config SSLOptions " 
    265                                 "StdEnvVars option being set") 
     305                            doc="Is an SSL request boolean " 
     306                                "- depends on Apache config") 
    266307     
    267308    def __init__(self, *arg, **kw): 
    268309        super(NDGSecurityPathFilter, self).__init__(*arg, **kw) 
    269         self._pathMatchList = [] 
    270310         
    271311    def _getPathMatchList(self): 
     
    286326        if isinstance(pathList, basestring): 
    287327            # Try parsing a space separated list of file paths 
    288              self._pathMatchList = pathList.split() 
     328             self._pathMatchList=[path.strip() for path in pathList.split(',')] 
    289329             
    290330        elif not isinstance(pathList, (list, tuple)): 
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/authn.py

    r4855 r4909  
    11"""HTTP Basic Authentication Middleware 
    22 
    3 NERC Data Grid Project 
     3NERC DataGrid Project 
    44 
    55""" 
     
    77__date__ = "13/01/09" 
    88__copyright__ = "(C) 2009 Science and Technology Facilities Council" 
     9__license__ = "BSD - see LICENSE file in top-level directory" 
    910__contact__ = "Philip.Kershaw@stfc.ac.uk" 
    1011__revision__ = "$Id$" 
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/openid/relyingparty/__init__.py

    r4907 r4909  
    3333        'signinInterfaceMiddlewareClass': None, 
    3434        'baseURL': '', 
    35         'sessionKey': 'beaker.session', 
    36         'reservedPaths': [] 
     35        'sessionKey': 'beaker.session' 
    3736    } 
    3837    propertyDefaults.update(NDGSecurityMiddlewareBase.propertyDefaults) 
     
    120119                log.debug('No referer set for redirect following logout') 
    121120                 
    122 #        if self.pathInfo not in self.reservedPaths: 
     121        # Set a return to address following logout.   
     122        # TODO: This code will need to be refactored if this middleware is  
     123        # deployed externally via a proxy - HTTP_REFERER will be the internal  
     124        # URI instead of the one exposed outside 
    123125        if 'HTTP_REFERER' in environ: 
    124126            session['ndg.security.server.wsgi.openid.relyingparty.referer'] = \ 
     
    150152 
    151153        return self._app(environ, set401UnauthorizedReponse) 
    152      
    153     def _redirect(self, url): 
    154         """Do a HTTP 302 redirect 
    155          
    156         @type url: basestring 
    157         @param url: URL to redirect to 
    158         @rtype: list 
    159         @return: empty HTML body 
    160         """ 
    161         self.start_response('302 %s' % httplib.responses[302],  
    162                             [('Content-type', 'text/html'), 
    163                              ('Location', url)]) 
    164         return [] 
    165154 
    166     def _setReservedPaths(self, paths): 
    167         if isinstance(paths, basestring): 
    168             self._reservedPaths = [path.strip() for path in paths.split(',')] 
    169         elif isinstance(paths, (tuple, list)): 
    170             self._reservedPaths = paths 
    171         else: 
    172             raise AttributeError("Reserved paths must be a string or list or " 
    173                                  "tuple") 
    174     def _getReservedPaths(self): 
    175         return self._reservedPaths 
    176      
    177     reservedPaths = property(fget=_getReservedPaths, 
    178                              fset=_setReservedPaths, 
    179                              doc="Set paths that logout redirect must avoid " 
    180                                  "e.g. AuthKit OpenID processing") 
    181155     
    182156class SigninInterfaceError(Exception): 
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/pep/__init__.py

    r4863 r4909  
    88__contact__ = "Philip.Kershaw@stfc.ac.uk" 
    99__revision__ = "$Id$" 
    10 __license__ = "BSD" 
     10__license__ = "BSD - see LICENSE file in top-levle directory" 
    1111import logging 
    1212log = logging.getLogger(__name__) 
     
    2727    sslServerDNKeyName = 'SSL_SERVER_S_DN' 
    2828      
    29     def __init__(self, *arg, **kw): 
     29    def __init__(self, app, app_conf, prefix='', **local_conf): 
    3030        log.debug("Initialising PEPMiddleware ...") 
    31         super(PEPMiddleware, self).__init__(*arg, **kw) 
     31         
     32        super(PEPMiddleware, self).__init__(app, app_conf, prefix=prefix,  
     33                                            **local_conf) 
    3234        self.charset = '; charset=utf-8' 
    3335 
    34     @NDGSecurityMiddlewareBase.initCall          
     36    @NDGSecurityPathFilter.initCall          
    3537    def __call__(self, environ, start_response): 
    36         log.debug("Calling PEPMiddleware.__call__ ...") 
     38        log.debug("PEPMiddleware.__call__ ...") 
    3739         
    38         # TODO: Is a security session set? 
    39         if True: 
    40             log.info('No security session is set') 
    41         else: 
    42             log.info('Security session is set') 
    43             if self.isSSLRequest: 
    44                  
    45                 response = self._redirectFromHTTPS2HTTP(start_response) 
    46                 if response is not None: 
    47                     return response 
    48                  
    4940        # Is this requested URL secured? 
    5041        if self.pathMatch: 
    51             return self._setErrorResponse(environ,  
    52                                           start_response, 
    53                                           code=self.errorResponseCode) 
     42#            return self._setErrorResponse(environ,  
     43#                                          start_response, 
     44#                                          code=self.errorResponseCode) 
     45            def _start_response(status, header, exc_info=None): 
     46                '''alter start_response to return unauthorised status 
     47                 
     48                @type status: str 
     49                @param status: HTTP status code and status message 
     50                @type header: list 
     51                @param header: list of field, value tuple HTTP header content 
     52                @type exc_info: Exception 
     53                @param exc_info: exception info 
     54                ''' 
     55                log.debug('[%s] is a secured URI: setting 403 status...' %  
     56                          self.pathInfo) 
     57                                         
     58                _status = self.getStatusMessage(403) 
     59                            
     60                return start_response(_status, header, exc_info) 
     61             
    5462        else: 
    55             # User is logged in - Redirect to HTTP based URL and complete 
    56             # Policy enforcement 
    57             pass 
    58 #            if self.isSSLRequest: 
    59 #                response = self._redirectFromHTTPS2HTTP(start_response) 
    60 #                if response is not None: 
    61 #                    return response 
     63            _start_response = start_response 
    6264             
    63         return self._setResponse(environ, start_response) 
     65        return self._setResponse(environ, _start_response) 
     66     
    6467 
    6568    def _redirectFromHTTPS2HTTP(self, start_response): 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/combinedservices/singlesignonservice/sso.cfg

    r4890 r4909  
    1616# content such as graphics and stylesheets 
    1717#configDir=%(here)s 
     18configDir=/home/pjkersha/workspace/security/python/ndg.security.server/ndg/security/server/sso/sso/badc_site 
    1819 
    1920# Switch from default templates package to templates/ in alternative directory 
    20 #templatesPackage: ndg.security.server.sso.sso.badc_site.templates 
     21templatesPackage: ndg.security.server.sso.sso.badc_site.templates 
    2122 
    2223# Redirect SOAP output to a file e.g. open(<somefile>, 'w') 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/openidrelyingparty/services.ini

    r4907 r4909  
    33# 
    44# Paste configuration for OpenID Relying Party test service 
    5 # * Session Manager 
    6 # * Attribute Authority 
    75# 
    86# The %(here)s variable will be replaced with the parent directory of this file 
     
    3432[filter:SessionMiddlewareFilter] 
    3533paste.filter_app_factory=beaker.middleware:SessionMiddleware 
    36 #beaker.session.key = sso 
    3734beaker.session.secret = somesecret 
    3835 
     
    4845 
    4946openid.relyingparty.sessionKey = beaker.session 
    50 openid.relyingparty.baseURL = http://localhost:5600 
    51 openid.relyingparty.reservedPaths = %(authkit.openid.path.process)s, %(authkit.openid.path.verify)s 
     47openid.relyingparty.baseURL = %(authkit.openid.baseurl)s 
    5248openid.relyingparty.signinInterfaceMiddlewareClass = ndg.security.server.wsgi.openid.relyingparty.signin_interface.buffet.BuffetSigninTemplate 
    5349openid.relyingparty.signinInterface.templatePackage = ndg.security.server.wsgi.openid.relyingparty.signin_interface.buffet.templates 
     
    7066authkit.cookie.signoutpath = /logout 
    7167authkit.openid.path.signedin=/ 
    72 #authkit.openid.path.process=/PROCESS 
    73 #authkit.openid.path.verify=/VERIFY 
    74 authkit.openid.path.process=/process 
    75 authkit.openid.path.verify=/verify 
    7668authkit.openid.store.type=file 
    7769authkit.openid.store.config=%(here)s/data/openid 
Note: See TracChangeset for help on using the changeset viewer.