Changeset 5037
- Timestamp:
- 25/02/09 13:52:50 (12 years ago)
- Location:
- TI12-security/trunk/python
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/python/Tests/sqlalchemy/test_sqlalchemy.py
r4544 r5037 3 3 from sqlalchemy import create_engine 4 4 5 from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey 6 7 class CreateResourceConstraintsDb(object): 8 9 def createResourceConstraintsTable(self): 10 metadata = MetaData() 11 users_table = Table('resource_constraints', metadata, 12 Column('id', Integer, primary_key=True), 13 Column('uri_regex', String)) 14 15 def createActionTypeTable(self): 16 metadata = MetaData() 17 users_table = Table('action_type', metadata, 18 Column('id', Integer, primary_key=True), 19 Column('uri_regex', String), 20 Column('action', String)) 21 22 def createAttributesTable(self): 23 metadata = MetaData() 24 users_table = Table('attributes', metadata, 25 Column('id', Integer, primary_key=True), 26 Column('uri_regex', String), 27 Column('attribute', String)) 28 5 29 if __name__ == "__main__": 6 30 import sys -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/pdp/__init__.py
r4975 r5037 114 114 115 115 # Alias for convenience 116 __call__ = accessPermitted 116 def __call__(self, *arg, **kw): 117 return self.accessPermitted(*arg, **kw) 117 118 -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/paster_templates/default_deployment/services.ini_tmpl
r4863 r5037 234 234 [filter:SessionMiddlewareFilter] 235 235 paste.filter_app_factory=beaker.middleware:SessionMiddleware 236 236 237 # Chain of SOAP Middleware filters 237 238 [pipeline:main] -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/__init__.py
r4909 r5037 266 266 # self.start_response will be None if initCall decorator wasn't 267 267 # applied to __call__ 268 if s tart_response is None:268 if self.start_response is None: 269 269 raise NDGSecurityMiddlewareConfigError("No start_response " 270 270 "function set.") -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/authn.py
r4909 r5037 10 10 __contact__ = "Philip.Kershaw@stfc.ac.uk" 11 11 __revision__ = "$Id$" 12 import logging 13 log = logging.getLogger(__name__) 12 14 from authkit.permissions import UserIn 13 from authkit.authorize import authorize14 15 15 16 from ndg.security.server.wsgi.utils.sessionmanagerclient import \ … … 37 38 else: 38 39 return True 40 41 import urllib 42 from urlparse import urlparse 43 from paste.request import construct_url 44 import authkit.authenticate 45 46 from ndg.security.server.wsgi import NDGSecurityMiddlewareBase, \ 47 NDGSecurityMiddlewareConfigError 48 49 class AuthNMiddleware(NDGSecurityMiddlewareBase): 50 '''Wrapper for AuthKit and Redirect middleware so that AuthKit Cookie 51 handler is called *before* redirect __call__. This is to enable the 52 latter to correctly check the login status updated by the AuthKit cookie 53 handler''' 54 triggerStatus = '401' 55 id = 'authNMiddleware' 56 57 def __init__(self, app, global_conf, **app_conf): 58 app = AuthNRedirectMiddleware(app, global_conf, **app_conf) 59 self._app = authkit.authenticate.middleware(app, app_conf) 60 # super(AuthNMiddleware, self).__init__(app, global_conf, **app_conf) 61 62 def __call__(self, environ, start_response): 63 return self._app(environ, start_response) 64 65 @classmethod 66 def checker(cls, environ, status, headers): 67 """Set the trigger for calling this middleware. In this case, it's a 68 HTTP 401 Unauthorized response detected in the middleware chain 69 """ 70 log.debug("AuthNMiddleware.checker received status %r, " 71 "headers %r", status, headers) 72 73 if status.startswith(cls.triggerStatus): 74 log.debug("AuthNMiddleware.checker returning True") 75 return True 76 else: 77 log.debug("AuthNMiddleware.checker returning False") 78 return False 79 80 class AuthNRedirectMiddlewareConfigError(NDGSecurityMiddlewareConfigError): 81 '''Authentication Redirect Middleware Configuration error''' 82 83 class AuthNRedirectMiddleware(NDGSecurityMiddlewareBase): 84 '''Middleware to redirect to another URI if no user is set in the 85 REMOTE_USER key of environ 86 87 AuthKit.authenticate.middleware must be in place upstream of this 88 middleware. AuthNMiddleware wrapper handles this. See above''' 89 propertyDefaults = { 90 'redirectURI': None, 91 'sessionKey': 'beaker.session' 92 } 93 propertyDefaults.update(NDGSecurityMiddlewareBase.propertyDefaults) 94 95 return2URIArgName = 'ndg.security.r' 96 logoutReturn2URIArgName = 'ndg.security.logout.r' 97 98 _isAuthenticated = lambda self: 'REMOTE_USER' in self.environ 99 isAuthenticated = property(fget=_isAuthenticated, 100 doc='boolean for is user logged in') 101 102 def __init__(self, app, global_conf, **app_conf): 103 self._redirectURI = None 104 105 # AuthKit params are expected to be present in 106 self._signoutPath = app_conf.get('authkit.cookie.signoutpath') 107 108 super(AuthNRedirectMiddleware, self).__init__(app, 109 global_conf, 110 **app_conf) 111 112 @NDGSecurityMiddlewareBase.initCall 113 def __call__(self, environ, start_response): 114 '''Invoke redirect if user is not authenticated''' 115 session = environ[self.sessionKey] 116 117 if not self.isAuthenticated: 118 # Redirect to OpenID Relying Party URI for user OpenID entry 119 return self._setRedirectResponse() 120 121 elif self._signoutPath is not None and \ 122 self.pathInfo == self._signoutPath: 123 referer = session.get( 124 AuthNRedirectMiddleware.logoutReturn2URIArgName) 125 if referer is not None: 126 def setRedirectResponse(status, header, exc_info=None): 127 header.extend([('Location', referer)]) 128 return start_response(self.getStatusMessage(302), 129 header, 130 exc_info) 131 132 return self._app(environ, setRedirectResponse) 133 else: 134 log.debug('No referer set for redirect following logout') 135 136 else: 137 # User is logged in, alter response to 403 to signal that an 138 # authorisation check is required and set a return to address for 139 # logout 140 session[AuthNRedirectMiddleware.logoutReturn2URIArgName] = \ 141 self.pathInfo 142 session.save() 143 144 def set403Response(status, header, exc_info=None): 145 return start_response(self.getStatusMessage(403), 146 header, 147 exc_info) 148 149 return self._app(environ, set403Response) 150 151 def _setRedirectURI(self, uri): 152 if not isinstance(uri, basestring): 153 raise TypeError("Redirect URI must be set to string type") 154 155 self._redirectURI = uri 156 157 def _getRedirectURI(self): 158 return self._redirectURI 159 160 redirectURI = property(fget=_getRedirectURI, 161 fset=_setRedirectURI, 162 doc="URI to redirect to if user is not authenticated") 163 164 def _setRedirectResponse(self): 165 """Construct a redirect response adding in a return to address in a 166 URI query argument 167 168 @rtype: basestring 169 @return: redirect response 170 """ 171 172 return2URI = construct_url(self.environ) 173 quotedReturn2URI = urllib.quote(return2URI, safe='') 174 return2URIQueryArg = urllib.urlencode( 175 {AuthNRedirectMiddleware.return2URIArgName: 176 quotedReturn2URI}) 177 178 redirectURI = self.redirectURI 179 180 if '?' in redirectURI: 181 if redirectURI.endswith('&'): 182 redirectURI += return2URIQueryArg 183 else: 184 redirectURI += '&' + return2URIQueryArg 185 else: 186 if redirectURI.endswith('?'): 187 redirectURI += return2URIQueryArg 188 else: 189 redirectURI += '?' + return2URIQueryArg 190 191 return self._redirect(redirectURI) 192 193 194 from authkit.authenticate.multi import MultiHandler 195 196 class AuthNRedirectHandlerMiddleware(MultiHandler, NDGSecurityMiddlewareBase): 197 '''Handler to intercept 401 Unauthorized HTTP responses and redirect to an 198 authentication URI. Add THIS class to any middleware chain and NOT 199 AuthNRedirectMiddleware which it wraps. 200 ''' 201 def __init__(self, app, global_conf, **app_conf): 202 MultiHandler.__init__(self, app) 203 204 self.add_method(AuthNMiddleware.id, 205 AuthNMiddleware.filter_app_factory, 206 global_conf, 207 **app_conf) 208 209 self.add_checker(AuthNMiddleware.id, AuthNMiddleware.checker) -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/openid/__init__.py
r4840 r5037 1 1 """WSGI Middleware components - OpenID package containing an OpenID Provider 2 WSGI implementation 2 and Relying Party WSGI implementations 3 3 4 4 NERC Data Grid Project""" -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/openid/relyingparty/__init__.py
r4909 r5037 15 15 16 16 import httplib # to get official status code messages 17 17 import urllib # decode quoted URI in query arg 18 from urlparse import urlparse 19 20 from paste.request import parse_querystring, parse_formvars 18 21 import authkit.authenticate 19 22 import beaker.middleware … … 86 89 87 90 authKitApp = authkit.authenticate.middleware(app, app_conf) 88 91 _app = authKitApp 92 while True: 93 if isinstance(_app,authkit.authenticate.open_id.AuthOpenIDHandler): 94 self._authKitVerifyPath = _app.path_verify 95 self._authKitProcessPath = _app.path_process 96 break 97 98 elif hasattr(_app, 'app'): 99 _app = _app.app 100 else: 101 break 102 103 if not hasattr(self, '_authKitVerifyPath'): 104 raise OpenIDRelyingPartyConfigError("Error locating the AuthKit " 105 "AuthOpenIDHandler in the " 106 "WSGI stack") 107 89 108 super(OpenIDRelyingPartyMiddleware, self).__init__(authKitApp, 90 109 global_conf, … … 96 115 def __call__(self, environ, start_response): 97 116 '''Alter start_response to override the status code and force to 401. 98 This will non-browser based client code to bypass the OpenID interface 117 This will enable non-browser based client code to bypass the OpenID 118 interface 99 119 100 120 @type environ: dict … … 104 124 ''' 105 125 session = environ[self.sessionKey] 126 127 # Check for return to address in URI query args 128 if environ['REQUEST_METHOD'] == "GET": 129 params = dict(parse_querystring(environ)) 130 else: 131 params = dict(parse_formvars(environ)) 132 133 referer = urllib.unquote(params.get('ndg.security.r', '')) 134 refererPathInfo = urlparse(referer)[2] 135 if referer and \ 136 not refererPathInfo.endswith(self._authKitVerifyPath) and \ 137 not refererPathInfo.endswith(self._authKitProcessPath): 138 # Set-up for authkit.authenticate.open_id.AuthOpenIDHandler.process 139 session['referer'] = referer 140 session.save() 141 106 142 if self.signoutPath is not None and self.pathInfo == self.signoutPath: 107 143 # TODO: Redirect to referrer ... -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/pdp.py
r4975 r5037 13 13 import httplib 14 14 15 from ndg.security.common.authz.pdp.xacml import PDP 15 from ndg.security.common.authz.pdp.xacml import PDP as XacmlPDP 16 from ndg.security.common.authz.pdp.xacml import Subject as XacmlSubject 17 from ndg.security.common.authz.pdp.xacml import Action as XacmlAction 18 from ndg.security.common.authz.pdp.xacml import Environment as XacmlEnvironment 16 19 17 20 from ndg.security.server.wsgi import NDGSecurityMiddlewareBase, \ 18 21 NDGSecurityMiddlewareConfigError 19 22 23 # TODO Refactor module placing 24 from ndg.security.server.wsgi.pep import Resource 25 26 class Subject(XacmlSubject): 27 def __init__(self): 28 self.sessionManagerURI = None 29 self.sessionManagerEnvironKey = None 30 self.userID = None 31 32 # TODO: may need to refactor out as attributes can be derived from the 33 # user's wallet held be the Session Manager 34 self.attributes = [] 35 36 class Action(XacmlAction): 37 pass 38 39 class Environment(XacmlEnvironment): 40 pass 41 42 class PDP(XacmlPDP): 43 def accessPermitted(self, subject, resource, action, environ): 44 '''Make access control decision''' 45 if action is None: 46 action = Action() 47 48 if environ is None: 49 environ = Environment() 50 51 super(PDP, self).accessPermitted(subject, resource, action, environ) 52 for attr in resource.attributes: 53 if attr in subject.attributes: 54 return True 55 56 return False 57 58 20 59 class PDPMiddlewareConfigError(NDGSecurityMiddlewareConfigError): 21 60 '''Policy Decision Point Middleware Configuration error''' 22 61 23 62 class PDPMiddleware(NDGSecurityMiddlewareBase): 24 forbiddenStatus = '403'63 triggerStatus = '403' 25 64 id = 'forbidden' 26 65 27 _isAuthenticated = lambda self: 'REMOTE_USER' in environ66 _isAuthenticated = lambda self: 'REMOTE_USER' in self.environ 28 67 isAuthenticated = property(fget=_isAuthenticated, 29 68 doc='boolean for is user logged in') … … 33 72 self.pdp = PDP() 34 73 35 @ PDPMiddleware.initCall74 @NDGSecurityMiddlewareBase.initCall 36 75 def __call__(self, environ, start_response): 37 76 if self.isAuthenticated: … … 51 90 '''Check constraints on the requested URI and return boolean - access 52 91 allowed/denied''' 53 status = self.pdp(subject, resource, action, environ) 92 environ = self.environ 93 94 # TODO: Refactor here perhaps calling resource constraint look-up or do 95 # inside PDP call? 96 resource = self.environ.get('ndg.security.server.wsgi.pep.resource') or \ 97 Resource() 98 subject = Subject() 99 subject.userID = self.environ.get('REMOTE_USER') 100 subject.attributes += ['someAttribute'] 101 status = self.pdp(subject, resource, None, None) 54 102 return status 55 103 … … 72 120 "%r", status, headers) 73 121 74 if status.startswith(cls. forbiddenStatus):122 if status.startswith(cls.triggerStatus): 75 123 log.debug("PDPMiddleware.checker returning True") 76 124 return True -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/pep/__init__.py
r4909 r5037 16 16 from ndg.security.common.X509 import X500DN 17 17 18 19 from ndg.security.server.wsgi import NDGSecurityMiddlewareBase, \ 20 NDGSecurityMiddlewareConfigError 21 22 # TODO: move this class to separate resource constraint module 23 from ndg.security.common.authz.pdp.xacml import Resource as XacmlResource 24 25 class Resource(XacmlResource): 26 def __init__(self, uri, attributes): 27 self.uri = uri 28 self.attributes = attributes 18 29 19 30 class PEPMiddleware(NDGSecurityPathFilter): … … 40 51 # Is this requested URL secured? 41 52 if self.pathMatch: 42 # return self._setErrorResponse(environ, 43 # start_response,44 # code=self.errorResponseCode)53 environ['ndg.security.server.wsgi.pep.resource'] = Resource( 54 self.pathInfo, 55 ['someAttribute']) 45 56 def _start_response(status, header, exc_info=None): 46 57 '''alter start_response to return unauthorised status -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/integration/authz/securedapp.ini
r5016 r5037 12 12 13 13 [pipeline:main] 14 pipeline = AuthNRedirectFilter 14 pipeline = SessionMiddlewareFilter 15 AuthenticationFilter 15 16 TestApp 16 17 17 18 [app:TestApp] 18 paste.app_factory = ndg.security.test. wsgi.authn.test_authn:TestAuthNMiddleware19 paste.app_factory = ndg.security.test.integration.authz.securedapp:TestAuthNMiddleware 19 20 20 [filter:AuthNRedirectFilter] 21 #______________________________________________________________________________ 22 # Beaker Session Middleware (used by Authentication Filter) 23 [filter:SessionMiddlewareFilter] 24 paste.filter_app_factory=beaker.middleware:SessionMiddleware 25 #beaker.session.key = sso 26 beaker.session.secret = somesecret 27 28 # If you'd like to fine-tune the individual locations of the cache data dirs 29 # for the Cache data, or the Session saves, un-comment the desired settings 30 # here: 31 beaker.cache.data_dir = %(here)s/beaker/cache 32 beaker.session.data_dir = %(here)s/beaker/sessions 33 34 [filter:AuthenticationFilter] 21 35 paste.filter_app_factory = ndg.security.server.wsgi.authn:AuthNRedirectHandlerMiddleware 22 36 prefix = authN. 23 authN.redirectURI = http://localhost:80443/verify 37 38 # Set redirect for OpenID Relying Party in the Security Services app instance 39 authN.redirectURI = http://localhost:7443/verify 40 41 # AuthKit Set-up 42 authkit.setup.method=cookie 43 authkit.cookie.secret=secret encryption string 44 authkit.cookie.signoutpath = /logout -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/integration/authz/securedapp.py
r5016 r5037 11 11 status = "401 Unauthorized" 12 12 13 elif environ['PATH_INFO'] == '/test_401WithLoggedIn':14 status = "401 Unauthorized"15 environ['REMOTE_USER'] = 'testuser'16 17 elif environ['PATH_INFO'] == '/test_200WithNotLoggedIn':18 status = "200 OK"19 20 elif environ['PATH_INFO'] == '/test_200WithLoggedIn':21 environ['REMOTE_USER'] = 'testuser'22 status = "200 OK"23 13 else: 24 14 status = "404 Not found" 25 15 26 start_response(status, 27 [('Content-length', 28 str(len(TestAuthNMiddleware.response))), 29 ('Content-type', 'text/plain')]) 30 return [TestAuthNMiddleware.response] 16 # start_response(status, 17 # [('Content-length', 18 # str(len(TestAuthNMiddleware.response))), 19 # ('Content-type', 'text/plain')]) 20 # return [TestAuthNMiddleware.response] 21 return self._setResponse(environ, start_response) 22 23 def _setResponse(self, environ, start_response): 24 if 'REMOTE_USER' in environ: 25 response = """<html> 26 <head/> 27 <body> 28 <p>Authenticated!</p> 29 <p><a href="/logout">logout</a></p> 30 </body> 31 </html>""" 32 start_response('200 OK', 33 [('Content-type', 'text/html'), 34 ('Content-length', str(len(response)))]) 35 else: 36 response = "Trigger OpenID Relying Party..." 37 start_response('401 Unauthorized', 38 [('Content-type', 'text/plain'), 39 ('Content-length', str(len(response)))]) 40 return [response] 31 41 32 42 def app_factory(globalConfig, **localConfig): … … 41 51 if __name__ == '__main__': 42 52 import sys 53 import os 54 from os.path import dirname, abspath 43 55 import logging 44 56 logging.basicConfig(level=logging.DEBUG) … … 47 59 port = int(sys.argv[1]) 48 60 else: 49 port = 8008061 port = 7080 50 62 51 63 cfgFilePath = os.path.join(dirname(abspath(__file__)), 'securedapp.ini') -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/integration/authz/securityservices.ini
r5017 r5037 18 18 use = egg:Paste#http 19 19 host = 0.0.0.0 20 port = 580020 port = 7443 21 21 22 22 # Play with this pipeline at your peril! ... … … 42 42 43 43 [app:AuthZTestApp] 44 paste.app_factory = ndg.security.test.integration.authz.se rverapp:app_factory44 paste.app_factory = ndg.security.test.integration.authz.securityservicesapp:app_factory 45 45 46 46 [filter:PEPMiddlewareFilter] … … 99 99 authkit.openid.session.secret = random string 100 100 101 authkit.openid.baseurl = http://localhost: 5800101 authkit.openid.baseurl = http://localhost:7443 102 102 103 103 # Template for signin -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/integration/authz/securityservicesapp.py
r5017 r5037 37 37 38 38 def default(self, environ, start_response): 39 start_response('200 OK', [('Content-type', 'text/plain')]) 40 return "Authorisation integration tests" 39 if 'REMOTE_USER' in environ: 40 response = """<html> 41 <head/> 42 <body> 43 <p>Authenticated!</p> 44 <p><a href="/logout">logout</a></p> 45 </body> 46 </html>""" 47 start_response('200 OK', 48 [('Content-type', 'text/html'), 49 ('Content-length', str(len(response)))]) 50 else: 51 response = "Authorisation integration tests" 52 start_response('200 OK', 53 [('Content-type', 'text/html'), 54 ('Content-length', str(len(response)))]) 55 return response 41 56 42 57 def test_401(self, environ, start_response): … … 102 117 port = int(sys.argv[1]) 103 118 else: 104 port = 80443119 port = 7443 105 120 106 cfgFilePath = os.path.join(dirname(abspath(__file__)), 'services.ini') 121 cfgFilePath = os.path.join(dirname(abspath(__file__)), 122 'securityservices.ini') 107 123 108 124 from paste.httpserver import serve -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/wsgi/authn/test.ini
r5015 r5037 21 21 paste.filter_app_factory = ndg.security.server.wsgi.authn:AuthNRedirectHandlerMiddleware 22 22 prefix = authN. 23 authN.redirectURI = /redirect2here 23 #authN.redirectURI = /redirect2here 24 authN.redirectURI = http://localhost:5800/verify -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/wsgi/authn/test_authn.py
r5015 r5037 28 28 import paste.fixture 29 29 from paste.deploy import loadapp 30 31 from ndg.security.server.wsgi.authn import AuthNRedirectHandlerMiddleware32 33 30 34 31 class TestAuthNMiddleware(object):
Note: See TracChangeset
for help on using the changeset viewer.