Changeset 7168
- Timestamp:
- 13/07/10 11:25:18 (11 years ago)
- Location:
- TI12-security/trunk/NDGSecurity/python
- Files:
-
- 2 added
- 4 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/authz/pep.py
r7164 r7168 8 8 from ndg.saml.saml2.binding.soap.client.authzdecisionquery import \ 9 9 AuthzDecisionQuerySslSOAPBinding 10 11 class SamlPepConfigError(Exception): 10 from ndg.security.server.wsgi.session import SessionHandlerMiddleware 11 12 13 class SamlPepMiddlewareConfigError(Exception): 12 14 """Error with SAML PEP configuration settings""" 13 15 … … 15 17 class SamlPepMiddleware(object): 16 18 '''Policy Enforcement Point for ESG with SAML based Interface 19 20 @requires: ndg.security.server.wsgi.session.SessionHandlerMiddleware 21 instance upstream in the WSGI stack. 22 23 @cvar AUTHZ_DECISION_QUERY_PARAMS_PREFIX: prefix for SAML authorisation 24 decision query options in config file 25 @type AUTHZ_DECISION_QUERY_PARAMS_PREFIX: string 26 27 @cvar PARAM_NAMES: list of config option names 28 @type PARAM_NAMES: tuple 17 29 18 30 @ivar __client: SAML authorisation decision query client … … 20 32 ''' 21 33 AUTHZ_DECISION_QUERY_PARAMS_PREFIX = 'authzDecisionQuery.' 22 AUTHZ_SERVICE_URI_PARAM_NAME = 'authzServiceURI' 23 24 __slots__ = ('_app', '__client', '__authzServiceURI') 34 SESSION_KEY_PARAM_NAME = 'sessionKey' 35 36 CREDENTIAL_WALLET_SESSION_KEYNAME = \ 37 SessionHandlerMiddleware.CREDENTIAL_WALLET_SESSION_KEYNAME 38 USERNAME_SESSION_KEYNAME = \ 39 SessionHandlerMiddleware.USERNAME_SESSION_KEYNAME 40 41 PARAM_NAMES = ( 42 'authzServiceURI', 43 'sessionKey' 44 ) 45 __slots__ = ( 46 '_app', '__client', '__session', 47 ) + tuple(["__%s" % i for i in PARAM_NAMES]) 48 del i 25 49 26 50 def __init__(self, app): … … 31 55 self._app = app 32 56 self.__client = AuthzDecisionQuerySslSOAPBinding() 57 self.__session = None 33 58 self.__authzServiceURI = None 34 59 self.__sessionKey = None 60 61 def _getClient(self): 62 return self.__client 63 64 def _setClient(self, value): 65 if not isinstance(value, basestring): 66 raise TypeError('Expecting string type for "client" attribute; ' 67 'got %r' % type(value)) 68 self.__client = value 69 70 client = property(_getClient, _setClient, 71 doc="SAML authorisation decision query SOAP client") 72 73 def _getSession(self): 74 return self.__session 75 76 def _setSession(self, value): 77 self.__session = value 78 79 session = property(_getSession, _setSession, 80 doc="Beaker Security Session instance") 81 82 def _getAuthzServiceURI(self): 83 return self.__authzServiceURI 84 85 def _setAuthzServiceURI(self, value): 86 if not isinstance(value, basestring): 87 raise TypeError('Expecting string type for "authzServiceURI" ' 88 'attribute; got %r' % type(value)) 89 self.__authzServiceURI = value 90 91 authzServiceURI = property(_getAuthzServiceURI, _setAuthzServiceURI, 92 doc="Authorisation Service URI") 93 94 def _getSessionKey(self): 95 return self.__sessionKey 96 97 def _setSessionKey(self, value): 98 if not isinstance(value, basestring): 99 raise TypeError('Expecting string type for "sessionKey" attribute; ' 100 'got %r' % type(value)) 101 self.__sessionKey = value 102 103 sessionKey = property(_getSessionKey, _setSessionKey, 104 doc="environ key name for Beaker session object") 105 35 106 def initialise(self, prefix='', **kw): 36 107 '''Initialise object from keyword settings 37 108 38 @type global_conf: dict39 @param global_conf: PasteDeploy global configuration dictionary40 109 @type prefix: basestring 41 110 @param prefix: prefix for configuration items 42 @type app_conf: dict43 @param app_conf: PasteDeploy application specific configuration111 @type kw: dict 112 @param kw: configuration settings 44 113 dictionary 45 @raise SamlPep ConfigError: no "authzServiceURI" setting114 @raise SamlPepMiddlewareConfigError: missing option setting(s) 46 115 ''' 116 # Parse authorisation decision query options 47 117 queryPrefix = prefix + self.__class__.AUTHZ_DECISION_QUERY_PARAMS_PREFIX 48 self.__client.parseKeywords(prefix=queryPrefix) 49 authzServiceUriParamName = prefix + \ 50 self.__class__.AUTHZ_SERVICE_URI_PARAM_NAME 51 52 self.__authzServiceURI = kw.get(authzServiceUriParamName) 53 if self.__authzServiceURI is None: 54 raise SamlPepConfigError('No %r setting for the authorisation ' 55 'service URI' % authzServiceUriParamName) 56 118 self.client.parseKeywords(prefix=queryPrefix, **kw) 119 120 # Parse other options 121 for name in SamlPepMiddleware.PARAM_NAMES: 122 paramName = prefix + name 123 value = kw.get(paramName) 124 if value is None: 125 raise SamlPepMiddlewareConfigError('Missing option %r' % 126 paramName) 127 setattr(self, name, value) 128 57 129 @classmethod 58 130 def filter_app_factory(cls, app, global_conf, prefix='', **app_conf): … … 85 157 @return: response 86 158 """ 159 # Get reference to session object - SessionHandler middleware must be in 160 # place upstream of this middleware in the WSGI stack 161 if self.sessionKey not in environ: 162 raise SamlPepMiddlewareConfigError('No beaker session key "%s" ' 163 'found in environ' % 164 self.sessionKey) 165 self.session = environ[self.sessionKey] 166 87 167 request = Request(environ) 88 168 self.__client.resourceURI = request.url 89 print dir(self.__client) 90 self.__client.subjectID = request.remote_user 169 self.__client.subjectID = request.remote_user or '' 91 170 92 171 self.__client.send(uri=self.__authzServiceURI) 172 173 return self._app(environ, start_response) 93 174 94 175 def _createAuthzDecisionQuery(self, -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/__init__.py
r7077 r7168 49 49 configDirEnvVarName = 'NDGSEC_TEST_CONFIG_DIR' 50 50 51 AUTHORISATION_SERVICE_PORTNUM = 9443 52 AUTHORISATION_SERVICE_URI = 'https://localhost:%s/authorisation-service' % \ 53 AUTHORISATION_SERVICE_PORTNUM 54 AUTHORISATION_SERVICE_INI_FILEPATH = mkDataDirPath( 55 os.path.join('authorisationservice', 'authorisation-service.ini')) 56 51 57 SITEA_ATTRIBUTEAUTHORITY_PORTNUM = 5000 52 58 SITEB_ATTRIBUTEAUTHORITY_PORTNUM = 5100 … … 192 198 BaseTestCase.SITEB_ATTRIBUTEAUTHORITY_PORTNUM), 193 199 withSSL=withSSL) 194 200 201 def startAuthorisationService(self, 202 withSSL=True, 203 port=AUTHORISATION_SERVICE_PORTNUM): 204 self.addService( 205 cfgFilePath=self.__class__.AUTHORISATION_SERVICE_INI_FILEPATH, 206 port=port, 207 withSSL=withSSL) 208 195 209 def __del__(self): 196 210 """Stop any services started with the addService method""" -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/wsgi/authz/saml-test.ini
r7164 r7168 21 21 paste.filter_app_factory=ndg.security.server.wsgi.authz.pep:SamlPepMiddleware.filter_app_factory 22 22 prefix = pep. 23 policy.filePath = %(here)s/saml-policy.xml 24 25 pep.authzServiceURI = https://localhost:9443/AuthorisationService 23 pep.sessionKey = beaker.session.ndg.security 24 pep.authzServiceURI = https://localhost:9443/authorisation-service 26 25 27 26 pep.pepResultHandler = ndg.security.test.unit.wsgi.authz.test_authz.RedirectFollowingAccessDenied … … 32 31 33 32 # If omitted, DN of SSL Cert is used 34 pep.authzDecisionQuery.issuerName = 33 pep.authzDecisionQuery.issuerName = /O=NDG/OU=BADC/CN=test 34 pep.authzDecisionQuery.issuerFormat = urn:oasis:names:tc:SAML:1.1:nameid-format:x509SubjectName 35 35 pep.authzDecisionQuery.subjectIdFormat = urn:esg:openid 36 36 pep.authzDecisionQuery.clockSkewTolerance = 0. -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/wsgi/authz/test_authz.py
r7164 r7168 29 29 from ndg.security.server.wsgi.authz.result_handler.redirect import \ 30 30 HTTPRedirectPEPResultHandlerMiddleware 31 from ndg.security.server.wsgi.authz import SamlPIPMiddlewareConfigError 32 31 from ndg.security.server.wsgi.authz.pep import SamlPepMiddlewareConfigError 32 33 34 from uuid import uuid4 35 from datetime import datetime, timedelta 36 37 from ndg.saml.saml2.core import (SAMLVersion, Subject, NameID, Issuer, 38 AuthzDecisionQuery, AuthzDecisionStatement, 39 Status, StatusCode, StatusMessage, 40 DecisionType, Action, Conditions, Assertion) 41 from ndg.saml.xml.etree import (AuthzDecisionQueryElementTree, 42 ResponseElementTree) 43 44 class TestAuthorisationServiceMiddleware(object): 45 """Test Authorisation Service interface stub""" 46 QUERY_INTERFACE_KEYNAME_OPTNAME = 'queryInterfaceKeyName' 47 RESOURCE_URI = 'http://localhost/dap/data/' 48 ISSUER_DN = '/O=Test/OU=Authorisation/CN=Service Stub' 49 50 def __init__(self, app, global_conf, **app_conf): 51 self.queryInterfaceKeyName = app_conf[ 52 TestAuthorisationServiceMiddleware.QUERY_INTERFACE_KEYNAME_OPTNAME] 53 self._app = app 54 55 def __call__(self, environ, start_response): 56 environ[self.queryInterfaceKeyName] = self.authzDecisionQueryFactory() 57 return self._app(environ, start_response) 58 59 def authzDecisionQueryFactory(self): 60 """Makes the authorisation decision""" 61 62 def authzDecisionQuery(query, response): 63 """Authorisation Decision Query interface called by the next 64 middleware in the stack the SAML SOAP Query interface middleware 65 instance 66 (ndg.saml.saml2.binding.soap.server.wsgi.queryinterface.SOAPQueryInterfaceMiddleware) 67 """ 68 now = datetime.utcnow() 69 response.issueInstant = now 70 71 # Make up a request ID that this response is responding to 72 response.inResponseTo = query.id 73 response.id = str(uuid4()) 74 response.version = SAMLVersion(SAMLVersion.VERSION_20) 75 76 response.status = Status() 77 response.status.statusCode = StatusCode() 78 response.status.statusCode.value = StatusCode.SUCCESS_URI 79 response.status.statusMessage = StatusMessage() 80 response.status.statusMessage.value = \ 81 "Response created successfully" 82 83 assertion = Assertion() 84 assertion.version = SAMLVersion(SAMLVersion.VERSION_20) 85 assertion.id = str(uuid4()) 86 assertion.issueInstant = now 87 88 authzDecisionStatement = AuthzDecisionStatement() 89 90 # Make some simple logic to simulate a full access policy 91 if query.resource == self.__class__.RESOURCE_URI: 92 if query.actions[0].value == Action.HTTP_GET_ACTION: 93 authzDecisionStatement.decision = DecisionType.PERMIT 94 else: 95 authzDecisionStatement.decision = DecisionType.DENY 96 else: 97 authzDecisionStatement.decision = DecisionType.INDETERMINATE 98 99 authzDecisionStatement.resource = query.resource 100 101 authzDecisionStatement.actions.append(Action()) 102 authzDecisionStatement.actions[-1].namespace = Action.GHPP_NS_URI 103 authzDecisionStatement.actions[-1].value = Action.HTTP_GET_ACTION 104 assertion.authzDecisionStatements.append(authzDecisionStatement) 105 106 # Add a conditions statement for a validity of 8 hours 107 assertion.conditions = Conditions() 108 assertion.conditions.notBefore = now 109 assertion.conditions.notOnOrAfter = now + timedelta(seconds=60*60*8) 110 111 assertion.subject = Subject() 112 assertion.subject.nameID = NameID() 113 assertion.subject.nameID.format = query.subject.nameID.format 114 assertion.subject.nameID.value = query.subject.nameID.value 115 116 assertion.issuer = Issuer() 117 assertion.issuer.format = Issuer.X509_SUBJECT 118 assertion.issuer.value = \ 119 TestAuthorisationServiceMiddleware.ISSUER_DN 120 121 response.assertions.append(assertion) 122 return response 123 124 return authzDecisionQuery 33 125 34 126 class RedirectFollowingAccessDenied(PEPResultHandlerMiddleware): … … 98 190 INI_FILE = 'saml-test.ini' 99 191 THIS_DIR = path.dirname(path.abspath(__file__)) 192 SESSION_KEYNAME = 'beaker.session.ndg.security' 193 100 194 def __init__(self, *args, **kwargs): 101 195 BaseTestCase.__init__(self, *args, **kwargs) … … 109 203 port=SamlWSGIAuthZTestCase.SITEA_SSL_ATTRIBUTEAUTHORITY_PORTNUM) 110 204 205 self.startAuthorisationService() 111 206 112 207 def test01CatchNoBeakerSessionFound(self): … … 114 209 # PEPFilterConfigError is raised if no beaker.session is set in 115 210 # environ 116 try: 117 response = self.app.get('/test_200') 118 except SamlPIPMiddlewareConfigError, e: 119 print("ok - expected: %s exception: %s" % (e.__class__, e)) 211 self.assertRaises(SamlPepMiddlewareConfigError, self.app.get, 212 '/test_200') 120 213 121 214 def test02Ensure200WithNotLoggedInAndUnsecuredURI(self): … … 125 218 126 219 # Simulate a beaker.session in the environ 127 extra_environ={ 'beaker.session.ndg.security':BeakerSessionStub()}220 extra_environ={self.__class__.SESSION_KEYNAME:BeakerSessionStub()} 128 221 response = self.app.get('/test_200', 129 222 extra_environ=extra_environ) … … 136 229 137 230 extra_environ = { 138 'beaker.session.ndg.security': 139 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI) 231 self.__class__.SESSION_KEYNAME: 232 BeakerSessionStub(username=self.__class__.OPENID_URI), 233 'REMOTE_USER': self.__class__.OPENID_URI 140 234 } 141 235 response = self.app.get('/test_401', … … 150 244 151 245 extra_environ = { 152 'beaker.session.ndg.security':246 self.__class__.SESSION_KEYNAME: 153 247 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI) 154 248 } … … 164 258 # AuthZ middleware checks for username key in session set by AuthN 165 259 # handler 166 extra_environ={ 'beaker.session.ndg.security':BeakerSessionStub()}260 extra_environ={self.__class__.SESSION_KEYNAME:BeakerSessionStub()} 167 261 response = self.app.get('/test_accessDeniedToSecuredURI', 168 262 extra_environ=extra_environ, … … 174 268 # access 175 269 extra_environ = { 176 'beaker.session.ndg.security':270 self.__class__.SESSION_KEYNAME: 177 271 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI) 178 272 } … … 190 284 # by the policy file 191 285 extra_environ = { 192 'beaker.session.ndg.security':286 self.__class__.SESSION_KEYNAME: 193 287 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI) 194 288 } … … 205 299 # access 206 300 extra_environ = { 207 'beaker.session.ndg.security':301 self.__class__.SESSION_KEYNAME: 208 302 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI) 209 303 } … … 231 325 THIS_DIR = os.path.dirname(os.path.abspath(__file__)) 232 326 INI_FILEPATH = path.join(THIS_DIR, INI_FILE) 327 SESSION_KEYNAME = 'beaker.session.ndg.security' 233 328 234 329 def __init__(self, *arg, **kw): … … 253 348 # access 254 349 extra_environ = { 255 'beaker.session.ndg.security':350 self.__class__.SESSION_KEYNAME: 256 351 BeakerSessionStub(username=self.__class__.OPENID_URI) 257 352 }
Note: See TracChangeset
for help on using the changeset viewer.