Changeset 7413


Ignore:
Timestamp:
02/09/10 09:28:06 (9 years ago)
Author:
pjkersha
Message:

Incomplete - task 2: XACML-Security Integration

  • added local PDP call to PEP to enable some requests to be filtered out as not applicable to the main authorisation service. Tested in ndg.security.test.unit.wsgi.authz.test_authz. TODO: add to integration tests.
Location:
TI12-security/trunk/NDGSecurity/python
Files:
6 edited
1 moved

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/authz/pep.py

    r7364 r7413  
    2020                                            AuthzDecisionQuerySslSOAPBinding 
    2121                                             
    22 from ndg.xacml import core as _xacmlCore 
     22from ndg.xacml.core import Identifiers as XacmlIdentifiers 
     23from ndg.xacml.core import context as _xacmlCtx 
     24from ndg.xacml.core.attribute import Attribute as XacmlAttribute 
     25from ndg.xacml.core.attributevalue import ( 
     26    AttributeValueClassFactory as XacmlAttributeValueClassFactory,  
     27    AttributeValue as XacmlAttributeValue) 
     28from ndg.xacml.core.context.result import Decision as XacmlDecision 
    2329from ndg.xacml.core.context.pdp import PDP 
    24 from ndg.xacml.core import context as _xacmlCtx 
    25 from ndg.xacml.parsers.etree.factory import ReaderFactory as \ 
    26     XacmlPolicyReaderFactory 
     30from ndg.xacml.parsers.etree.factory import ( 
     31    ReaderFactory as XacmlPolicyReaderFactory) 
    2732     
    2833from ndg.security.server.wsgi.session import (SessionMiddlewareBase,  
     
    5661    SESSION_KEY_PARAM_NAME = 'sessionKey' 
    5762    CACHE_DECISIONS_PARAM_NAME = 'cacheDecisions'    
    58     LOCAL_PDP_FILEPATH_PARAM_NAME = 'localPolicyFilePath' 
     63    LOCAL_POLICY_FILEPATH_PARAM_NAME = 'localPolicyFilePath' 
    5964     
    6065    CREDENTIAL_WALLET_SESSION_KEYNAME = \ 
     
    6772        SESSION_KEY_PARAM_NAME, 
    6873        CACHE_DECISIONS_PARAM_NAME, 
    69         LOCAL_PDP_FILEPATH_PARAM_NAME 
     74        LOCAL_POLICY_FILEPATH_PARAM_NAME 
    7075    ) 
     76     
     77    XACML_ATTRIBUTEVALUE_CLASS_FACTORY = XacmlAttributeValueClassFactory() 
     78     
    7179    __slots__ = ( 
    7280        '_app', '__client', '__session', '__localPdp' 
     
    201209                setattr(self, name, value) 
    202210                 
    203             elif value != self.__class__.LOCAL_PDP_FILEPATH_PARAM_NAME: 
     211            elif name != self.__class__.LOCAL_POLICY_FILEPATH_PARAM_NAME: 
    204212                # Policy file setting is optional 
    205213                raise SamlPepFilterConfigError('Missing option %r' % paramName) 
     
    260268        """ 
    261269        request = webob.Request(environ) 
     270        requestURI = request.url 
    262271         
    263272        # Apply local PDP if set 
    264         if self.__localPdp is not None: 
    265             self.__localPdp.evaluate() 
     273        if not self.isApplicableRequest(requestURI): 
     274            # The local PDP has returned a decision that the requested URI is 
     275            # not applicable and so the authorisation service need not be  
     276            # invoked.  This step is an efficiency measure to avoid multiple 
     277            # callouts to the authorisation service for resources which  
     278            # obviously don't need any restrictions  
     279            return self._app(environ, start_response) 
    266280             
    267281        # Check for cached decision 
    268282        if self.cacheDecisions: 
    269             assertions = self._retrieveCachedAssertions(request.url) 
     283            assertions = self._retrieveCachedAssertions(requestURI) 
    270284        else: 
    271285            assertions = None   
     
    284298            # Record the result in the user's session to enable later  
    285299            # interrogation by any result handler Middleware 
    286             self.setSession(self.client.query, samlAuthzResponse) 
     300            self.saveResultCtx(self.client.query, samlAuthzResponse) 
    287301         
    288302         
     
    317331             
    318332            response = webob.Response() 
     333            response.status = httplib.FORBIDDEN 
    319334            response.body = ('An error occurred retrieving an access decision ' 
    320335                             'for %r for user %r' % ( 
     
    374389        self.session.save() 
    375390         
    376     def setSession(self, request, response, save=True): 
     391    def saveResultCtx(self, request, response, save=True): 
    377392        """Set PEP context information in the Beaker session using standard key 
    378393        names.  This is a snapshot of the last request and the response  
     
    398413            self.session.save()      
    399414 
    400     def enforceFromLocalPdp(self, subjectId, resourceURI): 
     415    PDP_DENY_RESPONSES = ( 
     416        XacmlDecision.DENY_STR, XacmlDecision.INDETERMINATE_STR 
     417    ) 
     418     
     419    def isApplicableRequest(self, resourceURI): 
    401420        """A local PDP can filter out some requests to avoid the need to call 
    402421        out to the authorisation service  
    403         """ 
    404         xacmlRequest = self._createXacmlRequestCtx(subjectId, resourceURI) 
     422         
     423        @param resourceURI: URI of requested resource 
     424        @type resourceURI: basestring 
     425        """ 
     426        if self.__localPdp is None: 
     427            log.debug("No Local PDP set: passing on request to main " 
     428                      "authorisation service...") 
     429            return True 
     430         
     431        xacmlRequest = self._createXacmlRequestCtx(resourceURI) 
    405432        xacmlResponse = self.__localPdp.evaluate(xacmlRequest) 
     433        for result in xacmlResponse.results: 
     434            if result.decision.value != XacmlDecision.NOT_APPLICABLE_STR: 
     435                log.debug("Local PDP returned %s decision, passing request on " 
     436                          "to main authorisation service ...",  
     437                          result.decision.value) 
     438                return True 
     439             
     440        return False 
    406441 
    407442    def _createXacmlRequestCtx(self, resourceURI): 
     443        """Wrapper to create a request context for a local PDP - see  
     444        isApplicableRequest 
     445         
     446        @param resourceURI: URI of requested resource 
     447        @type resourceURI: basestring 
     448        """ 
    408449        request = _xacmlCtx.request.Request() 
    409450         
    410451        resource = _xacmlCtx.request.Resource() 
    411         resourceAttribute = _xacmlCore.attribute.Attribute() 
     452        resourceAttribute = XacmlAttribute() 
    412453        resource.attributes.append(resourceAttribute) 
    413454         
    414         resourceAttribute.attributeId = \ 
    415                                     _xacmlCore.Identifiers.Resource.RESOURCE_ID 
    416                              
    417         resourceAttribute.dataType = AnyUriAttributeValue.IDENTIFIER 
    418         resourceAttribute.attributeValues.append(AnyUriAttributeValue()) 
     455        resourceAttribute.attributeId = XacmlIdentifiers.Resource.RESOURCE_ID 
     456                                         
     457        XacmlAnyUriAttributeValue = \ 
     458            self.__class__.XACML_ATTRIBUTEVALUE_CLASS_FACTORY( 
     459                                            XacmlAttributeValue.ANY_TYPE_URI) 
     460                                     
     461        resourceAttribute.dataType = XacmlAnyUriAttributeValue.IDENTIFIER 
     462        resourceAttribute.attributeValues.append(XacmlAnyUriAttributeValue()) 
    419463        resourceAttribute.attributeValues[-1].value = resourceURI 
    420464 
  • TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/xacml/ctx_handler/saml_ctx_handler.py

    r7364 r7413  
    2525from ndg.xacml.core import context as _xacmlContext 
    2626from ndg.xacml.core.attribute import Attribute as XacmlAttribute 
    27 from ndg.xacml.core.attributevalue import AttributeValueClassFactory as \ 
    28     XacmlAttributeValueClassFactory 
     27from ndg.xacml.core.attributevalue import ( 
     28    AttributeValueClassFactory as XacmlAttributeValueClassFactory,  
     29    AttributeValue as XacmlAttributeValue) 
    2930from ndg.xacml.parsers.etree.factory import ReaderFactory as \ 
    3031    XacmlPolicyReaderFactory 
     
    377378                                         
    378379        XacmlAnyUriAttributeValue = xacmlAttributeValueFactory( 
    379                                     'http://www.w3.org/2001/XMLSchema#anyURI') 
     380                                            XacmlAttributeValue.ANY_TYPE_URI) 
    380381         
    381382        openidSubjectAttribute.dataType = XacmlAnyUriAttributeValue.IDENTIFIER 
     
    389390 
    390391        XacmlStringAttributeValue = xacmlAttributeValueFactory( 
    391                                     'http://www.w3.org/2001/XMLSchema#string') 
     392                                            XacmlAttributeValue.STRING_TYPE_URI) 
    392393                                   
    393394        xacmlRequest.subjects.append(xacmlSubject) 
  • TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/__init__.py

    r7358 r7413  
    1313import logging 
    1414import socket 
     15 
    1516logging.basicConfig() 
    1617log = logging.getLogger(__name__) 
  • TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/wsgi/authz/request-filter.xml

    r7364 r7413  
    3535        </Resources> 
    3636    </Target>    
     37    <Rule RuleId="Catch all" Effect="Deny"></Rule> 
    3738</Policy> 
  • TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/wsgi/authz/saml-test.ini

    r7354 r7413  
    2424pep.authzServiceURI = https://localhost:9443/authorisation-service 
    2525pep.cacheDecisions = True 
     26pep.localPolicyFilePath = %(here)s/request-filter.xml 
    2627 
    2728# Settings for Policy Information Point used by the Policy Decision Point to 
  • TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/wsgi/authz/test_authz.py

    r7287 r7413  
    1515import unittest 
    1616import os 
     17import time 
    1718from urlparse import urlunsplit 
    1819 
    1920from os import path 
    2021from ConfigParser import SafeConfigParser 
     22from urllib2 import URLError 
     23 
     24from uuid import uuid4 
     25from datetime import datetime, timedelta 
    2126 
    2227import paste.fixture 
    2328from paste.deploy import loadapp 
     29 
     30from ndg.saml.saml2.core import (SAMLVersion, Subject, NameID, Issuer,  
     31                                 AuthzDecisionQuery, AuthzDecisionStatement,  
     32                                 Status, StatusCode, StatusMessage,  
     33                                 DecisionType, Action, Conditions, Assertion) 
     34from ndg.saml.xml.etree import (AuthzDecisionQueryElementTree,  
     35                                ResponseElementTree) 
    2436 
    2537from ndg.security.test.unit import BaseTestCase 
     
    3042    HTTPRedirectPEPResultHandlerMiddleware 
    3143from ndg.security.server.wsgi.authz.pep import SamlPepFilterConfigError 
    32  
    33  
    34 from uuid import uuid4 
    35 from datetime import datetime, timedelta 
    36  
    37 from ndg.saml.saml2.core import (SAMLVersion, Subject, NameID, Issuer,  
    38                                  AuthzDecisionQuery, AuthzDecisionStatement,  
    39                                  Status, StatusCode, StatusMessage,  
    40                                  DecisionType, Action, Conditions, Assertion) 
    41 from ndg.saml.xml.etree import (AuthzDecisionQueryElementTree,  
    42                                 ResponseElementTree) 
    4344 
    4445 
     
    155156     
    156157    def __call__(self, environ, start_response): 
    157          
     158        response = self.__class__.RESPONSE 
    158159        if environ['PATH_INFO'] == '/test_401': 
    159160            status = "401 Unauthorized" 
     
    172173        elif environ['PATH_INFO'] == '/test_accessGrantedToSecuredURI': 
    173174            status = "200 OK" 
     175             
     176        elif environ['PATH_INFO'].startswith('/layout'): 
     177            status = "200 OK" 
     178            response += ("\n\nAny calls to this path or sub-path should be " 
     179                         "publicly accessible") 
    174180        else: 
    175181            status = "404 Not found" 
     
    177183        start_response(status, 
    178184                       [('Content-length',  
    179                          str(len(TestAuthZMiddleware.RESPONSE))), 
     185                         str(len(response))), 
    180186                        ('Content-type', 'text/plain')]) 
    181187         
     
    216222         
    217223        self.startAuthorisationService()   
    218            
     224     
    219225           
    220226class SamlPepFilterTestCase(BaseAuthzFilterTestCase): 
     
    272278 
    273279    def test05Catch401WithNotLoggedInAndSecuredURI(self): 
    274         # AuthZ middleware grants access because the URI requested has no 
    275         # subject restriction set in the policy rule 
     280        # User is not logged in and a secured resource has been requested so 401 
     281        # response is returned 
    276282         
    277283        # AuthZ middleware checks for username key in session set by AuthN 
    278284        # handler 
    279         extra_environ={self.__class__.SESSION_KEYNAME:BeakerSessionStub()}         
     285        extra_environ = {self.__class__.SESSION_KEYNAME: BeakerSessionStub()} 
    280286        response = self.app.get('/test_accessDeniedToSecuredURI', 
    281287                                extra_environ=extra_environ, 
     
    284290         
    285291    def test06AccessDeniedForSecuredURI(self): 
    286          
    287292        # User is logged in but doesn't have the required credentials for  
    288293        # access 
     
    298303        print response 
    299304 
    300     def test07AccessGrantedForSecuredURI(self): 
    301          
     305    def test07AccessGrantedForSecuredURI(self):       
    302306        # User is logged in and has credentials for access to a URI secured 
    303307        # by the policy file 
     
    313317        self.assert_(TestAuthZMiddleware.RESPONSE in response) 
    314318        print response 
    315  
     319         
     320    def test08LocalPolicyFiltersOutRequest(self): 
     321        # The local PDP filters out the incoming request as not applicable so 
     322        # that the authorisation service is never invoked. 
     323        extra_environ = {self.__class__.SESSION_KEYNAME: BeakerSessionStub()} 
     324        response = self.app.get('/layout/my.css', extra_environ=extra_environ, 
     325                                status=200) 
     326        self.assert_(response.body) 
     327                 
    316328 
    317329class PEPResultHandlerTestCase(BaseAuthzFilterTestCase): 
Note: See TracChangeset for help on using the changeset viewer.