source: TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/integration/__init__.py @ 7357

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/integration/__init__.py@7357
Revision 7357, 9.0 KB checked in by pjkersha, 10 years ago (diff)

Incomplete - task 2: XACML-Security Integration

  • implemented caching of authorisation decision statements in the PEP to cut down on calls to authorisation service.
  • Property svn:keywords set to Id
Line 
1"""NDG Security integration testing package
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "23/04/2009"
7__copyright__ = "(C) 2009 Science and Technology Facilities Council"
8__license__ = "BSD - see top-level directory for LICENSE file"
9__contact__ = "Philip.Kershaw@stfc.ac.uk"
10__revision__ = "$Id$"
11
12
13class AuthZTestApp(object):
14    """This class simulates the application to be secured by the NDG Security
15    authorization middleware
16    """
17    method = {
18"/": 'default',
19"/test_401": "test_401",
20"/test_403": "test_403",
21"/test_securedURI": "test_securedURI",
22"/test_accessDeniedToSecuredURI": "test_accessDeniedToSecuredURI",
23"/logout?ndg.security.logout.r=/test_logoutWithReturn2QueryArg": 
24    "test_logoutWithReturn2QueryArg",
25"/test_logoutViaHttpReferrer": "test_logoutViaHttpReferrer"
26    }
27    header = """        <h1>Authorisation Integration Tests:</h1>
28        <p>These tests use require the security services application to be
29        running.  See securityserviceapp.py and securityservices.ini in the
30        integration test directory.</p>
31        <h2>To Run:</h2>
32        <p>Try any of the links below.  When prompt for username and password,
33        enter one of the sets of credentials from securityservices.ini
34        openid.provider.authN.userCreds section.  The defaults are:
35        </p>
36        <p>pjk/testpassword</p>
37        <p>another/testpassword</p>
38        <p>The attributeinterface.py AttributeAuthority plugin is configured to
39        grant access to 'pjk' for all URLs below apart from
40        'test_accessDeniedToSecuredURI'.  The 'another' account will be denied
41        access from all URLs apart from 'test_401'</p>
42"""
43
44    def __init__(self, app, globalConfig, **localConfig):
45        self.beakerSessionKeyName = globalConfig['beakerSessionKeyName']
46        self.app = app
47           
48    def __call__(self, environ, start_response):
49       
50        methodName = self.method.get(environ['PATH_INFO'], '').rstrip()
51        if methodName:
52            action = getattr(self, methodName)
53            return action(environ, start_response)
54        elif environ['PATH_INFO'] == '/logout':
55            return self.default(environ, start_response)
56       
57        elif self.app is not None:
58            return self.app(environ, start_response)
59        else:
60            start_response('404 Not Found', [('Content-type', 'text/plain')])
61            return "Authorisation integration tests: invalid URI"
62           
63    def default(self, environ, start_response):
64        if 'username' in environ.get(self.beakerSessionKeyName, {}):
65            response = """<html>
66    <head/>
67    <body>
68        %s
69        <ul>%s</ul>
70        <p>You are logged in with OpenID [%s].  <a href="/logout">Logout</a></p>
71    </body>
72</html>
73""" % (AuthZTestApp.header,
74       '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
75                 for link,name in self.method.items() if name != 'default']),
76       environ[self.beakerSessionKeyName]['username'])
77       
78            start_response('200 OK', 
79                           [('Content-type', 'text/html'),
80                            ('Content-length', str(len(response)))])
81        else:
82            response = """<html>
83    <head/>
84    <body>
85        %s
86        <ul>%s</ul>
87    </body>
88</html>
89""" % (AuthZTestApp.header,
90       '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
91                 for link,name in self.method.items() if name != 'default'])
92       )
93
94            start_response('200 OK', 
95                           [('Content-type', 'text/html'),
96                            ('Content-length', str(len(response)))])
97        return response
98
99    def test_401(self, environ, start_response):
100        """Trigger the Authentication middleware by returning a 401
101        Unauthorized HTTP status code from this URI"""
102        username = environ[self.beakerSessionKeyName].get('username')
103        if username:
104            response = """<html>
105        <head/>
106        <body>
107            <h1>Authenticated!</h1>
108            <ul>%s</ul>
109            <p>You are logged in.  <a href="/logout">Logout</a></p>
110        </body>
111    </html>
112    """ % '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
113                     for link,name in self.method.items() if name != 'default'])
114   
115            start_response('200 OK', 
116                           [('Content-type', 'text/html'),
117                            ('Content-length', str(len(response)))])
118        else:
119            response = "This page shouldn't be displayed!"
120            start_response('401 Unauthorized', 
121                           [('Content-type', 'text/plain'),
122                            ('Content-length', str(len(response)))])
123           
124        return response
125
126    def test_403(self, environ, start_response):
127        """Trigger the Authorization middleware by returning a 403 Forbidden
128        HTTP status code from this URI"""
129       
130        username = environ[self.beakerSessionKeyName].get('username')
131        if username:
132            response = """<html>
133    <head/>
134    <body>
135        <h1>Authorised!</h1>
136        <ul>%s</ul>
137        <p>You are logged in with OpenID [%s].  <a href="/logout">Logout</a></p>
138    </body>
139</html>
140""" % ('\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
141                 for link,name in self.method.items() if name != 'default']),
142       username)
143
144            start_response('200 OK', 
145                           [('Content-type', 'text/html'),
146                            ('Content-length', str(len(response)))])
147        else:
148            response = "This page shouldn't be displayed!"
149            start_response('403 Forbidden', 
150                           [('Content-type', 'text/plain'),
151                            ('Content-length', str(len(response)))])
152
153        return response
154
155    def test_securedURI(self, environ, start_response):
156        """To be secured, the Authorization middleware must have this URI in
157        its policy"""
158        response = """<html>
159    <head/>
160    <body>
161        <h1>Authorised for path [%s]!</h1>
162        <ul>%s</ul>
163        <p>You are logged in with OpenID [%s].  <a href="/logout">Logout</a></p>
164    </body>
165</html>
166""" % (environ['PATH_INFO'],
167       '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
168                 for link,name in self.method.items() if name != 'default']),
169       environ[self.beakerSessionKeyName]['username'])
170
171
172        start_response('200 OK', 
173                       [('Content-type', 'text/html'),
174                        ('Content-length', str(len(response)))])
175        return response
176
177
178    def test_accessDeniedToSecuredURI(self, environ, start_response):
179        """To be secured, the Authorization middleware must have this URI in
180        its policy and the user must not have the required role as specified
181        in the policy.  See ndg.security.test.config.attributeauthority.sitea
182        for user role settings retrieved from the attribute authority"""
183        response = """<html>
184    <head/>
185    <body>
186        <h1>Authorised for path [%s]!</h1>
187        <ul>%s</ul>
188        <p>You are logged in with OpenID [%s].  <a href="/logout">Logout</a></p>
189    </body>
190</html>
191""" % (environ['PATH_INFO'],
192       '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
193                 for link,name in self.method.items() if name != 'default']),
194       environ[self.beakerSessionKeyName]['username'])
195
196
197        start_response('200 OK', 
198                       [('Content-type', 'text/html'),
199                        ('Content-length', str(len(response)))])
200        return response
201
202    def test_logoutWithReturn2QueryArg(self, environ, start_response):
203        """Test logout setting a return to argument to explicitly set the
204        URI to return to following the logout action
205        """
206        response = """<html>
207    <head/>
208    <body>
209        <h1>Logged Out</h1>
210        <p>Successfully redirected to specified return to URI query argument
211        ndg.security.logout.r=%s following logout. 
212        <a href="/">Return to tests</a></p>
213    </body>
214</html>
215""" % environ['PATH_INFO']
216
217        start_response('200 OK', 
218                       [('Content-type', 'text/html'),
219                        ('Content-length', str(len(response)))])
220        return response
221   
222    def test_logoutViaHttpReferrer(self, environ, start_response):
223        """Test logout - the middleware works out where to return to by checking
224        the HTTP_REFERER environ setting
225        """
226        response = """<html>
227    <head/>
228    <body>
229        <h1>Logged Out</h1>
230        <p>Successfully redirected to specified return to HTTP_REFERER=%s 
231        following logout. 
232        <a href="/">Return to tests</a></p>
233    </body>
234</html>
235""" % environ['PATH_INFO']
236
237        start_response('200 OK', 
238                       [('Content-type', 'text/html'),
239                        ('Content-length', str(len(response)))])
240        return response
241   
242    @classmethod
243    def app_factory(cls, globalConfig, **localConfig):
244        return cls(None, globalConfig, **localConfig)
245   
246    @classmethod
247    def filter_app_factory(cls, app, globalConfig, **localConfig):
248        return cls(app, globalConfig, **localConfig)
Note: See TracBrowser for help on using the repository browser.