source: TI12-security/trunk/python/ndg.security.test/ndg/security/test/integration/authz/securedapp.py @ 5223

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.test/ndg/security/test/integration/authz/securedapp.py@5223
Revision 5223, 7.8 KB checked in by pjkersha, 11 years ago (diff)

Updates following initial release on ndg3beta - release is now 1.0.1rc1:

  • Added additional test authN interface class for OpenID Provider BasicSessionManagerOpenIDAuthNInterface. This links to a session manager for authN but uses a simple look-up in the ini file to resolve usernames to OpenID identifiers. This is useful for testing. The production version SessionManagerOpenIDAuthNInterface uses a table in a database to do the same function.
  • improved ndg.security.server.wsgi.authn.AuthenticationRedirectMiddleware? log messaging for checker intercept method.
Line 
1#!/usr/bin/env python
2"""NDG Security test harness for authorisation middleware used to secure an
3application
4
5NERC DataGrid Project
6"""
7__author__ = "P J Kershaw"
8__date__ = "20/11/08"
9__copyright__ = "(C) 2009 Science and Technology Facilities Council"
10__license__ = "BSD - See top-level directory for LICENSE file"
11__contact__ = "Philip.Kershaw@stfc.ac.uk"
12__revision__ = "$Id$"
13
14   
15def app_factory(globalConfig, **localConfig):
16    return AuthZTestMiddleware(None, globalConfig, **localConfig)
17
18def filter_app_factory(app, globalConfig, **localConfig):
19    return AuthZTestMiddleware(app, globalConfig, **localConfig)
20
21class AuthZTestMiddleware(object):
22    """This class simulates the application to be secured by the NDG Security
23    authorization middleware
24    """
25    method = {
26"/": 'default',
27"/test_401": "test_401",
28"/test_403": "test_403",
29"/test_securedURI": "test_securedURI",
30"/test_accessDeniedToSecuredURI": "test_accessDeniedToSecuredURI"
31    }
32
33    def __init__(self, app, globalConfig, **localConfig):
34        self.app = app
35           
36    def __call__(self, environ, start_response):
37       
38        methodName = self.method.get(environ['PATH_INFO'], '').rstrip()
39        if methodName:
40            action = getattr(self, methodName)
41            return action(environ, start_response)
42        elif environ['PATH_INFO'] == '/logout':
43            return self.default(environ, start_response)
44       
45        elif self.app is not None:
46            return self.app(environ, start_response)
47        else:
48            start_response('404 Not Found', [('Content-type', 'text/plain')])
49            return "Authorisation integration tests: invalid URI"
50           
51    def default(self, environ, start_response):
52        if 'REMOTE_USER' in environ:
53            response = """<html>
54    <head/>
55    <body>
56        <h1>Authorisation integration tests:</h1>
57        <ul>%s</ul>
58        <p>You are logged in.  <a href="/logout">Logout</a></p>
59    </body>
60</html>
61""" % '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
62                 for link,name in self.method.items() if name != 'default'])
63       
64            start_response('200 OK', 
65                           [('Content-type', 'text/html'),
66                            ('Content-length', str(len(response)))])
67        else:
68            response = """<html>
69    <head/>
70    <body>
71        <h1>Authorisation integration tests:</h1>
72        <ul>%s</ul>
73    </body>
74</html>
75""" % '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
76                 for link,name in self.method.items() if name != 'default'])
77
78            start_response('200 OK', 
79                           [('Content-type', 'text/html'),
80                            ('Content-length', str(len(response)))])
81        return response
82
83    def test_401(self, environ, start_response):
84        if 'REMOTE_USER' in environ:
85            response = """<html>
86    <head/>
87    <body>
88        <h1>Authenticated!</h1>
89        <ul>%s</ul>
90        <p>You are logged in.  <a href="/logout">Logout</a></p>
91    </body>
92</html>
93""" % '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
94                 for link,name in self.method.items() if name != 'default'])
95
96            start_response('200 OK', 
97                           [('Content-type', 'text/html'),
98                            ('Content-length', str(len(response)))])
99        else:
100            response = "Trigger OpenID Relying Party..."
101            start_response('401 Unauthorized', 
102                           [('Content-type', 'text/plain'),
103                            ('Content-length', str(len(response)))])
104        return response
105
106    def test_403(self, environ, start_response):
107        """Trigger the Authorization middleware by returning a 403 Forbidden
108        HTTP status code from this URI"""
109       
110        if 'REMOTE_USER' in environ:
111            response = """<html>
112    <head/>
113    <body>
114        <h1>Authorised!</h1>
115        <ul>%s</ul>
116        <p>You are logged in.  <a href="/logout">Logout</a></p>
117    </body>
118</html>
119""" % '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
120                 for link,name in self.method.items() if name != 'default'])
121
122            start_response('200 OK', 
123                           [('Content-type', 'text/html'),
124                            ('Content-length', str(len(response)))])
125        else:
126            response = ("Authorization middleware is triggered becuase this "
127                        "page returns a 403 Forbidden status.")
128            start_response('403 Forbidden', 
129                           [('Content-type', 'text/plain'),
130                            ('Content-length', str(len(response)))])
131        return response
132
133    def test_securedURI(self, environ, start_response):
134        """To be secured, the Authorization middleware must have this URI in
135        its policy"""
136        if 'REMOTE_USER' in environ:
137            response = """<html>
138    <head/>
139    <body>
140        <h1>Authorised for path [%s]!</h1>
141        <ul>%s</ul>
142        <p>You are logged in.  <a href="/logout">Logout</a></p>
143    </body>
144</html>
145""" % (environ['PATH_INFO'],
146       '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
147                 for link,name in self.method.items() if name != 'default']))
148
149
150            start_response('200 OK', 
151                           [('Content-type', 'text/html'),
152                            ('Content-length', str(len(response)))])
153        else:
154            response = ("Authorization middleware must have this URI in its "
155                        "policy in order to secure it!")
156            start_response('200 OK', 
157                           [('Content-type', 'text/plain'),
158                            ('Content-length', str(len(response)))])
159        return response
160
161
162    def test_accessDeniedToSecuredURI(self, environ, start_response):
163        """To be secured, the Authorization middleware must have this URI in
164        its policy and the user must not have the required role as specified
165        in the policy.  See ndg.security.test.config.attributeauthority.sitea
166        for user role settings retrieved from the attribute authority"""
167        if 'REMOTE_USER' in environ:
168            response = """<html>
169    <head/>
170    <body>
171        <h1>Authorised for path [%s]!</h1>
172        <ul>%s</ul>
173        <p>You are logged in.  <a href="/logout">Logout</a></p>
174    </body>
175</html>
176""" % (environ['PATH_INFO'],
177       '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
178                 for link,name in self.method.items() if name != 'default']))
179
180
181            start_response('200 OK', 
182                           [('Content-type', 'text/html'),
183                            ('Content-length', str(len(response)))])
184        else:
185            response = ("Authorization middleware must have this URI in its "
186                        "policy in order to secure it!")
187            start_response('200 OK', 
188                           [('Content-type', 'text/plain'),
189                            ('Content-length', str(len(response)))])
190        return response
191   
192    @classmethod
193    def app_factory(cls, globalConfig, **localConfig):
194        return cls(None, globalConfig, **localConfig)
195   
196    @classmethod
197    def filter_app_factory(cls, app, globalConfig, **localConfig):
198        return cls(app, globalConfig, **localConfig)
199   
200# To start run
201# $ paster serve services.ini or run this file as a script
202# $ ./securedapp.py [port #]
203if __name__ == '__main__':
204    import sys
205    import os
206    from os.path import dirname, abspath
207    import logging
208    logging.basicConfig(level=logging.DEBUG)
209
210    if len(sys.argv) > 1:
211        port = int(sys.argv[1])
212    else:
213        port = 7080
214       
215    cfgFilePath = os.path.join(dirname(abspath(__file__)), 'securedapp.ini')
216       
217    from paste.httpserver import serve
218    from paste.deploy import loadapp
219   
220    app = loadapp('config:%s' % cfgFilePath)
221    serve(app, host='0.0.0.0', port=port)
Note: See TracBrowser for help on using the repository browser.