Ignore:
Timestamp:
09/09/08 15:19:47 (11 years ago)
Author:
pjkersha
Message:

Refined SOAP and WS-Security WSGI middleware. TODO: pass all Attribute Authority unit tests and integrate Session Manager.

File:
1 edited

Legend:

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

    r4172 r4185  
    2929     
    3030class WSSecurityFilter(SOAPMiddleware): 
    31     """Base class for WS-Security filters""" 
    32     def __init__(self, app, app_conf): 
    33         self.app = app 
    34         self.app_conf = app_conf 
     31    """Base class for WS-Security filters 
     32     
     33    Overload pathMatch lambda so that it is more inclusive: the default is 
     34    for all paths to be processed by the handlers""" 
     35    pathMatch = lambda self, environ: \ 
     36                        environ['PATH_INFO'].startswith(self.app_conf['path']) 
    3537 
    36 class WSSecuritySignatureFilter(WSSecurityFilter): 
     38class SignatureFilter(WSSecurityFilter): 
    3739    """Base class for WS-Security signature and signature verification filters 
    3840    """ 
    39     def __init__(self, app, app_conf): 
    40         super(WSSecuritySignatureFilter).__init__(app, app_conf) 
     41    def __init__(self, app, app_conf, **kw): 
     42        super(SignatureFilter, self).__init__(app, app_conf, **kw) 
    4143         
    4244        wsseCfgFilePath = self.app_conf.get('wsseCfgFilePath') 
     
    4749            
    4850     
    49 class SignatureFilter(WSSecuritySignatureFilter): 
     51class ApplySignatureFilter(SignatureFilter): 
    5052    '''Apply WS-Security digital signature to SOAP message''' 
    5153    def __call__(self, environ, start_response): 
    52         if not self.isSOAPMessage(environ): 
     54        '''Sign message''' 
     55        if not self.isSOAPMessage(environ) or \ 
     56           not self.pathMatch(environ): 
     57            log.debug("ApplySignatureFilter.__call__: Non-SOAP " 
     58                      "request or path doesn't match SOAP endpoint specified " 
     59                      "- skipping signature verification") 
    5360            return self.app(environ, start_response) 
    5461         
    5562        log.debug('Signing outbound message ...') 
    56         app = self.app(environ, start_response) 
    57  
    58         sw = self.getSOAPWriter(environ) 
    59         self.signatureHandler.sign(sw) 
    60         soapOut_ = str(sw) 
     63        if self.isSOAPFaultSet(environ): 
     64            # TODO: If the Signature handler is signing any sub-elements in the 
     65            # message body this is going to run into problems because the  
     66            # fault content is obviously going to be different. 
     67            # TODO: Should SOAP faults be signed at all? 
     68            log.warning("Attempting to sign a SOAP fault message...") 
     69             
     70        try: 
     71            sw = self.getSOAPWriter(environ) 
     72        except Exception, e: 
     73            sw = self.exception2SOAPFault(environ, e) 
     74            self.setSOAPWriter(environ, sw) 
     75             
     76        try: 
     77            self.signatureHandler.sign(sw) 
     78        except Exception, e: 
     79            sw = self.exception2SOAPFault(environ, e) 
     80            self.setSOAPWriter(environ, sw) 
    6181         
    62         def start_response_wrapper(status, response_hdrs, exc_info=None): 
    63             '''Ensure correct content length''' 
    64              
    65             log.debug("Altering content-length to allow for signature...") 
    66             contentKeys = ('content-length', ) 
    67             response_hdrs_alt = [(name, val) for name, val in response_hdrs\ 
    68                                  if name.lower() not in contentKeys] 
    69              
    70             response_hdrs_alt += [('content-length', str(len(soapOut_)))] 
    71       
    72             return start_response(status, response_hdrs_alt, exc_info) 
    73  
    74         def app(environ, start_response_wrapper): 
    75             return soapOut_ 
    76          
    77         return app 
     82        return self.writeResponse(environ, start_response) 
    7883     
    7984 
    80 class SignatureVerificationFilter(WSSecuritySignatureFilter): 
     85class SignatureVerificationFilter(SignatureFilter): 
    8186    '''Verify WS-Security digital signature in SOAP message''' 
    8287     
    8388    def __call__(self, environ, start_response): 
    84         if not self.isSOAPMessage(environ): 
    85             log.debug("Non-SOAP request: Skipping signature verification") 
     89        '''Verify message signature''' 
     90        if not self.isSOAPMessage(environ) or \ 
     91           not self.pathMatch(environ): 
     92            log.debug("SignatureVerificationFilter.__call__: Non-SOAP " 
     93                      "request or path doesn't match SOAP endpoint specified " 
     94                      "- skipping signature verification") 
    8695            return self.app(environ, start_response) 
    8796 
    8897        log.debug("Verifying inbound message signature...") 
    89         
    90         ps = self.parse(environ) 
    91         self.signatureHandler.verify(ps) 
    92          
    93         # Pass on in environment as an efficiency measure for any following 
    94         # SOAP Middleware 
    95         return self.app(environ, start_response) 
    9698 
    97  
    98 def makeSignatureVerificationFilter(app, global_conf): 
    99     return SignatureVerificationFilter(app, global_conf)  
    100  
    101 def makeSignatureFilter(app, global_conf): 
    102     return SignatureFilter(app, global_conf) 
     99        try: 
     100            ps = self.parseRequest(environ) 
     101            self.signatureHandler.verify(ps) 
     102        except Exception, e: 
     103            sw = self.exception2SOAPFault(environ, e) 
     104            self.setSOAPWriter(environ, sw) 
     105             
     106        return self.writeResponse(environ, start_response) 
Note: See TracChangeset for help on using the changeset viewer.