source: TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/integration/authz_lite/securedapp.py @ 7077

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/integration/authz_lite/securedapp.py@7077
Revision 7077, 9.2 KB checked in by pjkersha, 10 years ago (diff)
  • Property svn:keywords set to Id
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    '''AuthZTestMiddleware factory for Paste app pattern'''
17    return AuthZTestMiddleware(None, globalConfig, **localConfig)
18
19def filter_app_factory(app, globalConfig, **localConfig):
20    '''AuthZTestMiddleware factory for Paste filter app pattern'''
21    return AuthZTestMiddleware(app, globalConfig, **localConfig)
22
23class AuthZTestMiddleware(object):
24    """This class simulates the application to be secured by the NDG Security
25    authorization middleware
26    """
27    method = {
28"/": 'default',
29"/test_401": "test_401",
30"/test_403": "test_403",
31"/test_securedURI": "test_securedURI",
32"/test_accessDeniedToSecuredURI": "test_accessDeniedToSecuredURI"
33    }
34    header = """        <h1>Authorisation Integration Tests:</h1>
35        <p>Test Authorisation middleware with no Session Manager running.
36        See the authz/ integration test directory for a configuration including
37        a Session Manager</p>
38        <p>These tests use require the security services application to be
39        running.  See securityserviceapp.py and securityservices.ini in the
40        authz_lite/ integration test directory.</p>
41        <h2>To Run:</h2>
42        <p>Try any of the links below.  When prompt for username and password,
43        enter one of the sets of credentials from securityservices.ini
44        openid.provider.authN.userCreds section.  The defaults are:
45        </p>
46        <p>pjk/testpassword</p>
47        <p>another/testpassword</p>
48        <p>The attributeinterface.py AttributeAuthority plugin is configured to
49        grant access to 'pjk' for all URLs below apart from
50        'test_accessDeniedToSecuredURI'.  The 'another' account will be denied
51        access from all URLs apart from 'test_401'</p>
52"""
53
54    def __init__(self, app, globalConfig, **localConfig):
55        self.app = app
56           
57    def __call__(self, environ, start_response):
58       
59        methodName = self.method.get(environ['PATH_INFO'], '').rstrip()
60        if methodName:
61            action = getattr(self, methodName)
62            return action(environ, start_response)
63        elif environ['PATH_INFO'] == '/logout':
64            return self.default(environ, start_response)
65       
66        elif self.app is not None:
67            return self.app(environ, start_response)
68        else:
69            start_response('404 Not Found', [('Content-type', 'text/plain')])
70            return "Authorisation integration tests: invalid URI"
71           
72    def default(self, environ, start_response):
73        if 'REMOTE_USER' in environ:
74            response = """<html>
75    <head/>
76    <body>
77        %s
78        <ul>%s</ul>
79        <p>You are logged in with OpenID [%s].  <a href="/logout">Logout</a></p>
80    </body>
81</html>
82""" % (AuthZTestMiddleware.header,
83       '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
84                 for link,name in self.method.items() if name != 'default']),
85       environ['REMOTE_USER'])
86       
87            start_response('200 OK', 
88                           [('Content-type', 'text/html'),
89                            ('Content-length', str(len(response)))])
90        else:
91            response = """<html>
92    <head/>
93    <body>
94        %s
95        <ul>%s</ul>
96    </body>
97</html>
98""" % (AuthZTestMiddleware.header,
99       '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
100                 for link,name in self.method.items() if name != 'default'])
101       )
102
103            start_response('200 OK', 
104                           [('Content-type', 'text/html'),
105                            ('Content-length', str(len(response)))])
106        return response
107
108    def test_401(self, environ, start_response):
109        if 'REMOTE_USER' in environ:
110            response = """<html>
111    <head/>
112    <body>
113        <h1>Authenticated!</h1>
114        <ul>%s</ul>
115        <p>You are logged in.  <a href="/logout">Logout</a></p>
116    </body>
117</html>
118""" % '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
119                 for link,name in self.method.items() if name != 'default'])
120
121            start_response('200 OK', 
122                           [('Content-type', 'text/html'),
123                            ('Content-length', str(len(response)))])
124        else:
125            response = "Trigger OpenID Relying Party..."
126            start_response('401 Unauthorized', 
127                           [('Content-type', 'text/plain'),
128                            ('Content-length', str(len(response)))])
129        return response
130
131    def test_403(self, environ, start_response):
132        """Trigger the Authorization middleware by returning a 403 Forbidden
133        HTTP status code from this URI"""
134       
135        if 'REMOTE_USER' in environ:
136            response = """<html>
137    <head/>
138    <body>
139        <h1>Authorised!</h1>
140        <ul>%s</ul>
141        <p>You are logged in with OpenID [%s].  <a href="/logout">Logout</a></p>
142    </body>
143</html>
144""" % ('\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
145                 for link,name in self.method.items() if name != 'default']),
146       environ['REMOTE_USER'])
147
148            start_response('200 OK', 
149                           [('Content-type', 'text/html'),
150                            ('Content-length', str(len(response)))])
151        else:
152            response = ("Authorization middleware is triggered becuase this "
153                        "page returns a 403 Forbidden status.")
154            start_response('403 Forbidden', 
155                           [('Content-type', 'text/plain'),
156                            ('Content-length', str(len(response)))])
157        return response
158
159    def test_securedURI(self, environ, start_response):
160        """To be secured, the Authorization middleware must have this URI in
161        its policy"""
162        if 'REMOTE_USER' in environ:
163            response = """<html>
164    <head/>
165    <body>
166        <h1>Authorised for path [%s]!</h1>
167        <ul>%s</ul>
168        <p>You are logged in with OpenID [%s].  <a href="/logout">Logout</a></p>
169    </body>
170</html>
171""" % (environ['PATH_INFO'],
172       '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
173                 for link,name in self.method.items() if name != 'default']),
174       environ['REMOTE_USER'])
175
176
177            start_response('200 OK', 
178                           [('Content-type', 'text/html'),
179                            ('Content-length', str(len(response)))])
180        else:
181            response = ("Authorization middleware must have this URI in its "
182                        "policy in order to secure it!")
183            start_response('200 OK', 
184                           [('Content-type', 'text/plain'),
185                            ('Content-length', str(len(response)))])
186        return response
187
188
189    def test_accessDeniedToSecuredURI(self, environ, start_response):
190        """To be secured, the Authorization middleware must have this URI in
191        its policy and the user must not have the required role as specified
192        in the policy.  See ndg.security.test.config.attributeauthority.sitea
193        for user role settings retrieved from the attribute authority"""
194        if 'REMOTE_USER' in environ:
195            response = """<html>
196    <head/>
197    <body>
198        <h1>Authorised for path [%s]!</h1>
199        <ul>%s</ul>
200        <p>You are logged in with OpenID [%s].  <a href="/logout">Logout</a></p>
201    </body>
202</html>
203""" % (environ['PATH_INFO'],
204       '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 
205                 for link,name in self.method.items() if name != 'default']),
206       environ['REMOTE_USER'])
207
208
209            start_response('200 OK', 
210                           [('Content-type', 'text/html'),
211                            ('Content-length', str(len(response)))])
212        else:
213            response = ("Authorization middleware must have this URI in its "
214                        "policy in order to secure it!")
215            start_response('200 OK', 
216                           [('Content-type', 'text/plain'),
217                            ('Content-length', str(len(response)))])
218        return response
219   
220    @classmethod
221    def app_factory(cls, globalConfig, **localConfig):
222        return cls(None, globalConfig, **localConfig)
223   
224    @classmethod
225    def filter_app_factory(cls, app, globalConfig, **localConfig):
226        return cls(app, globalConfig, **localConfig)
227   
228# To start run
229# $ paster serve services.ini or run this file as a script
230# $ ./securedapp.py [port #]
231if __name__ == '__main__':
232    import sys
233    import os
234    from os.path import dirname, abspath
235    import logging
236    logging.basicConfig(level=logging.DEBUG)
237
238    if len(sys.argv) > 1:
239        port = int(sys.argv[1])
240    else:
241        port = 7080
242       
243    cfgFilePath = os.path.join(dirname(abspath(__file__)), 'securedapp.ini')
244       
245    from paste.httpserver import serve
246    from paste.deploy import loadapp
247    from paste.script.util.logging_config import fileConfig
248   
249    fileConfig(cfgFilePath)
250    app = loadapp('config:%s' % cfgFilePath)
251    serve(app, host='0.0.0.0', port=port)
Note: See TracBrowser for help on using the repository browser.