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

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

Fixes to Attribute Authority for SAML SOAP binding code forked into ndg.saml

  • Property svn:keywords set to Id
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
13logging.basicConfig(level=logging.DEBUG)
14
15import unittest
16import os
17from urlparse import urlunsplit
18
19from os import path
20from ConfigParser import SafeConfigParser
21
22import paste.fixture
23from paste.deploy import loadapp
24
25from ndg.security.test.unit import BaseTestCase
26from ndg.security.server.wsgi import NDGSecurityMiddlewareBase
27from ndg.security.server.wsgi.authz.result_handler.basic import \
28    PEPResultHandlerMiddleware
29from ndg.security.server.wsgi.authz.result_handler.redirect import \
30    HTTPRedirectPEPResultHandlerMiddleware
31from ndg.security.server.wsgi.authz import SamlPIPMiddlewareConfigError
32
33
34class RedirectFollowingAccessDenied(PEPResultHandlerMiddleware):
35   
36    @NDGSecurityMiddlewareBase.initCall
37    def __call__(self, environ, start_response):
38       
39        queryString = environ.get('QUERY_STRING', '')
40        if 'admin=1' in queryString:
41            # User has been rejected access to a URI requiring admin rights,
42            # try redirect to the same URI minus the admin query arg, this
43            # request will pass because admin rights aren't needed
44            queryArgs = queryString.split('&')
45            queryList = [arg for arg in queryArgs if arg != 'admin=1']
46            editedQuery = '&'.join(queryList)
47            redirectURI = urlunsplit(('', '', self.pathInfo, editedQuery, ''))
48            return self.redirect(redirectURI)
49        else:
50            return super(RedirectFollowingAccessDenied, self).__call__(
51                                                            environ,
52                                                            start_response)
53
54       
55class TestAuthZMiddleware(object):
56    '''Test Application for the Authentication handler to protect'''
57    response = "Test Authorization application"
58       
59    def __init__(self, app_conf, **local_conf):
60        pass
61   
62    def __call__(self, environ, start_response):
63       
64        if environ['PATH_INFO'] == '/test_401':
65            status = "401 Unauthorized"
66           
67        elif environ['PATH_INFO'] == '/test_403':
68            status = "403 Forbidden"
69           
70        elif environ['PATH_INFO'] == '/test_200':
71            status = "200 OK"
72           
73        elif environ['PATH_INFO'] == '/test_accessDeniedToSecuredURI':
74            # Nb. AuthZ middleware should intercept the request and bypass this
75            # response
76            status = "200 OK"
77           
78        elif environ['PATH_INFO'] == '/test_accessGrantedToSecuredURI':
79            status = "200 OK"
80        else:
81            status = "404 Not found"
82               
83        start_response(status,
84                       [('Content-length', 
85                         str(len(TestAuthZMiddleware.response))),
86                        ('Content-type', 'text/plain')])
87        return [TestAuthZMiddleware.response]
88
89
90class BeakerSessionStub(dict):
91    """Emulate beaker.session session object for purposes of the unit tests
92    """
93    def save(self):
94        pass
95 
96   
97class SamlWSGIAuthZTestCase(BaseTestCase):
98    INI_FILE = 'saml-test.ini'
99    THIS_DIR = path.dirname(path.abspath(__file__))
100    def __init__(self, *args, **kwargs):       
101        BaseTestCase.__init__(self, *args, **kwargs)
102
103       
104        wsgiapp = loadapp('config:'+SamlWSGIAuthZTestCase.INI_FILE, 
105                          relative_to=SamlWSGIAuthZTestCase.THIS_DIR)
106        self.app = paste.fixture.TestApp(wsgiapp)
107       
108        self.startSiteAAttributeAuthority(withSSL=True,
109            port=SamlWSGIAuthZTestCase.SITEA_SSL_ATTRIBUTEAUTHORITY_PORTNUM)
110       
111
112    def test01CatchNoBeakerSessionFound(self):
113       
114        # PEPFilterConfigError is raised if no beaker.session is set in
115        # environ
116        try:
117            response = self.app.get('/test_200')
118        except SamlPIPMiddlewareConfigError, e:
119            print("ok - expected: %s exception: %s" % (e.__class__, e))
120       
121    def test02Ensure200WithNotLoggedInAndUnsecuredURI(self):
122       
123        # Check the authZ middleware leaves the response alone if the URI
124        # is not matched in the policy
125       
126        # Simulate a beaker.session in the environ
127        extra_environ={'beaker.session.ndg.security':BeakerSessionStub()}
128        response = self.app.get('/test_200',
129                                extra_environ=extra_environ)
130
131    def test03Catch401WithLoggedIn(self):
132       
133        # Check that the application being secured can raise a HTTP 401
134        # response and that this respected by the Authorization middleware
135        # even though a user is set in the session
136       
137        extra_environ = {
138            'beaker.session.ndg.security':
139                BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI)
140        }
141        response = self.app.get('/test_401', 
142                                extra_environ=extra_environ,
143                                status=401)
144
145    def test04Catch403WithLoggedIn(self):
146       
147        # Check that the application being secured can raise a HTTP 403
148        # response and that this respected by the Authorization middleware
149        # even though a user is set in the session
150       
151        extra_environ = {
152            'beaker.session.ndg.security':
153                BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI)
154        }
155        response = self.app.get('/test_403', 
156                                extra_environ=extra_environ,
157                                status=403)
158
159    def test05Catch401WithNotLoggedInAndSecuredURI(self):
160       
161        # AuthZ middleware grants access because the URI requested is not
162        # targeted in the policy
163       
164        # AuthZ middleware checks for username key in session set by AuthN
165        # handler
166        extra_environ={'beaker.session.ndg.security':BeakerSessionStub()}       
167        response = self.app.get('/test_accessDeniedToSecuredURI',
168                                extra_environ=extra_environ,
169                                status=401)
170       
171    def test06AccessDeniedForSecuredURI(self):
172       
173        # User is logged in but doesn't have the required credentials for
174        # access
175        extra_environ = {
176            'beaker.session.ndg.security':
177                BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI)
178        }
179       
180        response = self.app.get('/test_accessDeniedToSecuredURI',
181                                extra_environ=extra_environ,
182                                status=403)
183        print response
184        self.assert_("Insufficient privileges to access the "
185                     "resource" in response)
186
187    def test07AccessGrantedForSecuredURI(self):
188       
189        # User is logged in and has credentials for access to a URI secured
190        # by the policy file
191        extra_environ = {
192            'beaker.session.ndg.security':
193                BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI)
194        }
195       
196        response = self.app.get('/test_accessGrantedToSecuredURI',
197                                extra_environ=extra_environ,
198                                status=200)
199        self.assert_(TestAuthZMiddleware.response in response)
200        print response
201
202    def test08AccessDeniedForAdminQueryArg(self):
203       
204        # User is logged in but doesn't have the required credentials for
205        # access
206        extra_environ = {
207            'beaker.session.ndg.security':
208                BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI)
209        }
210       
211        # Try this URI with the query arg admin=1.  This will be picked up
212        # by the policy as a request requiring admin rights.  The request is
213        # denied as the user doesn't have these rights but this then calls
214        # into play the PEP result handler defined in this module,
215        # RedirectFollowingAccessDenied.  This class reinvokes the request
216        # but without the admin query argument.  Access is then granted for
217        # the redirected request
218        response = self.app.get('/test_accessGrantedToSecuredURI',
219                                params={'admin': 1},
220                                extra_environ=extra_environ,
221                                status=302)
222        try:
223            redirectResponse = response.follow(extra_environ=extra_environ)
224        except paste.fixture.AppError, e:
225            self.failIf(TestAuthZMiddleware.response not in response)
226        print response
227
228
229class PEPResultHandlerTestCase(BaseTestCase):
230    INI_FILE = 'pep-result-handler-test.ini'
231    THIS_DIR = os.path.dirname(os.path.abspath(__file__))
232    INI_FILEPATH = path.join(THIS_DIR, INI_FILE)
233   
234    def __init__(self, *arg, **kw):
235        BaseTestCase.__init__(self, *arg, **kw)
236       
237        here_dir = os.path.dirname(os.path.abspath(__file__))
238        wsgiapp = loadapp('config:'+self.__class__.INI_FILE, 
239                          relative_to=self.__class__.THIS_DIR)
240        self.app = paste.fixture.TestApp(wsgiapp)
241       
242        cfg = SafeConfigParser(dict(here=self.__class__.THIS_DIR))
243        cfg.read(self.__class__.INI_FILEPATH)
244        self.redirectURI = cfg.get('filter:AuthZFilter', 
245                                   'authz.pepResultHandler.redirectURI')
246       
247        self.startSiteAAttributeAuthority(withSSL=True,
248            port=SamlWSGIAuthZTestCase.SITEA_SSL_ATTRIBUTEAUTHORITY_PORTNUM)
249
250       
251    def testRedirectPEPResultHandlerMiddleware(self):
252        # User is logged in but doesn't have the required credentials for
253        # access
254        extra_environ = {
255            'beaker.session.ndg.security':
256                        BeakerSessionStub(username=self.__class__.OPENID_URI)
257        }
258       
259        # Expecting redirect response to specified redirect URI
260        response = self.app.get('/test_accessDeniedToSecuredURI',
261                                extra_environ=extra_environ,
262                                status=302)
263        print(response)
264        self.assert_(response.header_dict.get('location') == self.redirectURI)
265       
266if __name__ == "__main__":
267    unittest.main()       
Note: See TracBrowser for help on using the repository browser.