source: TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/wsgi/authz/test_authz.py @ 5330

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/wsgi/authz/test_authz.py@5330
Revision 5330, 8.7 KB checked in by pjkersha, 11 years ago (diff)

Completed AuthorizationMiddleware? unit tests ndg.security.test.unit.wsgi.authz:

  • Test 8, 'test08AccessDeniedForAdminQueryArg' tries out the use case for a URI which can display additional content for users with admin privileges. The caller needs to be able to display the correct content according to whether the user has admin rights or not:
    1. the caller invokes /securedURI?admin=1
    2. if the user has admin, rights the PDP will grant access and the PEP will deliver this URI.
    3. if the user doesn't have admin rights, a special overloaded PEP result handler class detects that access was denied for the admin URI and redirects the user to a modified URI subtracting the admin flag. The application code can then deliver the appropriate content minus admin privileges.
Line 
1#!/usr/bin/env python
2"""Unit tests for WSGI Authorization handler
3
4NERC DataGrid Project
5"""
6__author__ = "P J Kershaw"
7__date__ = "21/05/09"
8__copyright__ = "(C) 2009 Science and Technology Facilities Council"
9__license__ = "BSD - see LICENSE file in top-level directory"
10__contact__ = "Philip.Kershaw@stfc.ac.uk"
11__revision__ = '$Id$'
12import logging
13
14
15import unittest
16import os
17from urlparse import urlunsplit
18
19from os.path import expandvars as xpdVars
20from os.path import join as jnPath
21mkPath = lambda file: jnPath(os.environ['NDGSEC_COMBINED_SRVS_UNITTEST_DIR'], 
22                             file)
23
24import paste.fixture
25from paste.deploy import loadapp
26from ndg.security.server.wsgi import NDGSecurityMiddlewareBase
27from ndg.security.server.wsgi.authz import PEPFilterConfigError, \
28    PEPResultHandlerMiddleware
29from ndg.security.common.authz.msi import Response
30
31class RedirectFollowingAccessDenied(PEPResultHandlerMiddleware):
32   
33    @NDGSecurityMiddlewareBase.initCall
34    def __call__(self, environ, start_response):
35       
36        queryString = environ.get('QUERY_STRING', '')
37        if 'admin=1' in queryString:
38            # User has been rejected access to a URI requiring admin rights,
39            # try redirect to the same URI minus the admin query arg, this
40            # request will pass because admin rights aren't needed
41            queryArgs = queryString.split('&')
42            queryList = [arg for arg in queryArgs if arg != 'admin=1']
43            editedQuery = '&'.join(queryList)
44            redirectURI = urlunsplit(('', '', self.pathInfo, editedQuery, ''))
45            return self.redirect(redirectURI)
46        else:
47            return super(RedirectFollowingAccessDenied, self).__call__(
48                                                            environ,
49                                                            start_response)
50       
51class TestAuthZMiddleware(object):
52    '''Test Application for the Authentication handler to protect'''
53    response = "Test Authorization application"
54       
55    def __init__(self, app_conf, **local_conf):
56        pass
57   
58    def __call__(self, environ, start_response):
59       
60        if environ['PATH_INFO'] == '/test_401':
61            status = "401 Unauthorized"
62           
63        elif environ['PATH_INFO'] == '/test_403':
64            status = "403 Forbidden"
65           
66        elif environ['PATH_INFO'] == '/test_200':
67            status = "200 OK"
68           
69        elif environ['PATH_INFO'] == '/test_accessDeniedToSecuredURI':
70            # Nb. AuthZ middleware should intercept the request and bypass this
71            # response
72            status = "200 OK"
73           
74        elif environ['PATH_INFO'] == '/test_accessGrantedToSecuredURI':
75            status = "200 OK"
76        else:
77            status = "404 Not found"
78               
79        start_response(status,
80                       [('Content-length', 
81                         str(len(TestAuthZMiddleware.response))),
82                        ('Content-type', 'text/plain')])
83        return [TestAuthZMiddleware.response]
84
85class BeakerSessionStub(dict):
86    """Emulate beaker.session session object for purposes of the unit tests
87    """
88    def save(self):
89        pass
90   
91class WSGIAuthZTestController(unittest.TestCase):
92
93    def __init__(self, *args, **kwargs):
94        here_dir = os.path.dirname(os.path.abspath(__file__))
95        wsgiapp = loadapp('config:test.ini', relative_to=here_dir)
96        self.app = paste.fixture.TestApp(wsgiapp)
97         
98        unittest.TestCase.__init__(self, *args, **kwargs)
99       
100
101    def test01CatchNoBeakerSessionFound(self):
102       
103        # PEPFilterConfigError is raised if no beaker.session is set in
104        # environ
105        try:
106            response = self.app.get('/test_200')
107        except PEPFilterConfigError, e:
108            print("PASS - expected: %s exception: %s" % (e.__class__, e))
109       
110    def test02Ensure200WithNotLoggedInAndUnsecuredURI(self):
111       
112        # Check the authZ middleware leaves the response alone if the URI
113        # is not matched in the policy
114       
115        # Simulate a beaker.session in the environ
116        extra_environ={'beaker.session.ndg.security':BeakerSessionStub()}
117        response = self.app.get('/test_200',
118                                extra_environ=extra_environ)
119
120    def test03Catch401WithLoggedIn(self):
121       
122        # Check that the application being secured can raise a HTTP 401
123        # response and that this respected by the Authorization middleware
124        # even though a user is set in the session
125       
126        extra_environ={'beaker.session.ndg.security':
127                       BeakerSessionStub(username='testuser')}
128        response = self.app.get('/test_401', 
129                                extra_environ=extra_environ,
130                                status=401)
131
132    def test04Catch403WithLoggedIn(self):
133       
134        # Check that the application being secured can raise a HTTP 403
135        # response and that this respected by the Authorization middleware
136        # even though a user is set in the session
137       
138        extra_environ={'beaker.session.ndg.security':
139                       BeakerSessionStub(username='testuser')}
140        response = self.app.get('/test_403', 
141                                extra_environ=extra_environ,
142                                status=403)
143
144    def test05Catch401WithNotLoggedInAndSecuredURI(self):
145       
146        # AuthZ middleware grants access because the URI requested is not
147        # targeted in the policy
148       
149        # AuthZ middleware checks for username key in session set by AuthN
150        # handler
151        extra_environ={'beaker.session.ndg.security':BeakerSessionStub()}       
152        response = self.app.get('/test_accessDeniedToSecuredURI',
153                                extra_environ=extra_environ,
154                                status=401)
155       
156    def test06AccessDeniedForSecuredURI(self):
157       
158        # User is logged in but doesn't have the required credentials for
159        # access
160        extra_environ={'beaker.session.ndg.security':
161                       BeakerSessionStub(username='testuser')}
162       
163        response = self.app.get('/test_accessDeniedToSecuredURI',
164                                extra_environ=extra_environ,
165                                status=403)
166        self.failIf(
167            "Insufficient privileges to access the resource" not in response)
168        print response
169       
170    def test07AccessGrantedForSecuredURI(self):
171       
172        # User is logged in but doesn't have the required credentials for
173        # access
174        extra_environ={'beaker.session.ndg.security':
175                       BeakerSessionStub(username='testuser')}
176       
177        response = self.app.get('/test_accessGrantedToSecuredURI',
178                                extra_environ=extra_environ,
179                                status=200)
180        self.failIf(TestAuthZMiddleware.response not in response)
181        print response
182
183    def test07AccessGrantedForSecuredURI(self):
184       
185        # User is logged in and has credentials for access to a URI secured
186        # by the policy file
187        extra_environ={'beaker.session.ndg.security':
188                       BeakerSessionStub(username='testuser')}
189       
190        response = self.app.get('/test_accessGrantedToSecuredURI',
191                                extra_environ=extra_environ,
192                                status=200)
193        self.assert_(TestAuthZMiddleware.response in response)
194        print response
195
196    def test08AccessDeniedForAdminQueryArg(self):
197       
198        # User is logged in but doesn't have the required credentials for
199        # access
200        extra_environ={'beaker.session.ndg.security':
201                       BeakerSessionStub(username='testuser')}
202       
203        # Try this URI with the query arg admin=1.  This will be picked up
204        # by the policy as a request requiring admin rights.  The request is
205        # denied as the user doesn't have these rights but this then calls
206        # into play the PEP result handler defined in this module,
207        # RedirectFollowingAccessDenied.  This class reinvokes the request
208        # but without the admin query argument.  Access is then granted for
209        # the redirected request
210        response = self.app.get('/test_accessGrantedToSecuredURI',
211                                params={'admin': 1},
212                                extra_environ=extra_environ,
213                                status=302)
214        try:
215            redirectResponse = response.follow(extra_environ=extra_environ)
216        except paste.fixture.AppError, e:
217            self.failIf(TestAuthZMiddleware.response not in response)
218        print response
219
220if __name__ == "__main__":
221    unittest.main()       
Note: See TracBrowser for help on using the repository browser.