Changeset 6788 for TI12-security/trunk/NDGSecurity
- Timestamp:
- 30/03/10 13:22:59 (11 years ago)
- Location:
- TI12-security/trunk/NDGSecurity/python
- Files:
-
- 4 added
- 2 deleted
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/soap/client.py
r6584 r6788 25 25 class SOAPClientBase(object): 26 26 """Handle client request to a SOAP Service 27 @cvar RESPONSE_CONTENT_TYPES: expected content type to be returned in a response28 from a service27 @cvar RESPONSE_CONTENT_TYPES: expected content type to be returned in a 28 response from a service 29 29 @type RESPONSE_CONTENT_TYPES: string 30 30 """ -
TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/utils/factory.py
r6686 r6788 34 34 objectName = objectName.split('.') 35 35 else: 36 _moduleName, objectName = moduleName.rsplit('.', 1) 36 try: 37 _moduleName, objectName = moduleName.rsplit('.', 1) 38 except ValueError: 39 raise ValueError('Invalid module name %r set for import: %s' % 40 (moduleName, traceback.format_exc())) 41 37 42 objectName = [objectName] 38 43 else: -
TI12-security/trunk/NDGSecurity/python/ndg_security_common/setup.py
r6628 r6788 24 24 # TODO: subdivide these into server and client specific and comon dependencies 25 25 _pkgDependencies = [ 26 'PyXML', # include as a separate dependency to force correct download link27 26 'ZSI', 28 27 '4Suite-XML', 29 28 'M2Crypto', 30 'ndg_s ecurity_saml'29 'ndg_saml' 31 30 ] 32 33 # TODO: configure an option so that database support can be set for the34 # Credential Repository. MySQL package may need to be in its own option35 # eventually36 credentialRepositoryDbSupport = False37 if credentialRepositoryDbSupport:38 _pkgDependencies += [39 'SQLObject',40 'MySQL-python', # TODO: fix gcc error: unrecognized option `-restrict'41 ]42 31 43 32 # Python 2.5 includes ElementTree by default -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/attributeauthority.py
r6730 r6788 38 38 from ndg.security.common.saml_utils.esg import EsgSamlNamespaces 39 39 from ndg.security.common.X509 import X500DN 40 from ndg.security.common.utils import TypedList , RestrictedKeyNamesDict40 from ndg.security.common.utils import TypedList 41 41 from ndg.security.common.utils.classfactory import instantiateClass 42 42 from ndg.security.common.utils.configfileparsers import ( … … 63 63 interface for Earth System Grid 64 64 65 @type propertyDefaults: dict66 @cvar propertyDefaults: valid configuration property keywords65 @type PROPERTY_DEFAULTS: dict 66 @cvar PROPERTY_DEFAULTS: valid configuration property keywords 67 67 68 68 @type ATTRIBUTE_INTERFACE_PROPERTY_DEFAULTS: dict … … 109 109 # Values set to not NotImplemented here denote keys which must be specified 110 110 # in the config 111 propertyDefaults= {111 PROPERTY_DEFAULTS = { 112 112 ISSUER_NAME_OPTNAME: '', 113 113 ASSERTION_LIFETIME_OPTNAME: -1, … … 135 135 self.__propPrefix = '' 136 136 137 self.__attributeInterfaceCfg = RestrictedKeyNamesDict(138 AttributeAuthority.ATTRIBUTE_INTERFACE_PROPERTY_DEFAULTS)137 self.__attributeInterfaceCfg = \ 138 AttributeAuthority.ATTRIBUTE_INTERFACE_PROPERTY_DEFAULTS.copy() 139 139 140 140 def __getstate__(self): … … 390 390 continue 391 391 392 if name not in AttributeAuthority. propertyDefaults:392 if name not in AttributeAuthority.PROPERTY_DEFAULTS: 393 393 raise AttributeError('Invalid attribute name "%s"' % name) 394 394 … … 396 396 val = os.path.expandvars(val) 397 397 398 if isinstance(AttributeAuthority. propertyDefaults[name], list):398 if isinstance(AttributeAuthority.PROPERTY_DEFAULTS[name], list): 399 399 val = AttributeAuthority.CONFIG_LIST_SEP_PAT.split(val) 400 400 -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/authz/__init__.py
r6604 r6788 26 26 AttributeQuerySslSOAPBinding 27 27 28 from ndg.security.common.credentialwallet import (NDGCredentialWallet, 29 SAMLCredentialWallet) 28 from ndg.security.common.credentialwallet import SAMLCredentialWallet 30 29 from ndg.security.server.wsgi import (NDGSecurityMiddlewareBase, 31 30 NDGSecurityMiddlewareConfigError) … … 43 42 PIPAttributeResponse) 44 43 45 # The NDG Interface Subject type includes support for Session Manager related 46 # keywords which are not needed by the newer SamlPIPMiddleware 47 from ndg.security.common.authz.pip.ndginterface import PIP, Subject 48 from ndg.security.common.authz.msi import (Policy, PDP, Request, 49 Response, Resource) 44 from ndg.security.common.authz import Subject 45 from ndg.security.common.authz.msi import (Policy, PDP, Request, Response, 46 Resource) 50 47 51 48 … … 56 53 class PEPFilterConfigError(PEPFilterError): 57 54 """Configuration related error for PEPFilter""" 55 58 56 59 57 class PEPFilter(SessionMiddlewareBase): … … 154 152 "user authorisation ...") 155 153 156 # Make a request object to pass to the PDP. Set an NDG type Subject 157 # which has the extra keyword support for Session Manager and 158 # Session ID needed by NdgPIPMiddleware. This can be deprecated in a 159 # future release when the SOAP/WSL attribute interface is withdrawn 160 # and completely replaced by the SAML one 161 request = Request(subject=Subject()) 154 # Make a request object to pass to the PDP. 155 request = Request() 162 156 request.subject[Subject.USERID_NS] = session['username'] 163 164 # IdP Session Manager specific settings:165 #166 # The following won't be set if the IdP running the OpenID Provider167 # hasn't also deployed a Session Manager. In this case, the168 # Attribute Authority will be queried directly from here without a169 # remote Session Manager intermediary to cache credentials170 request.subject[Subject.SESSIONID_NS] = session.get('sessionId')171 request.subject[Subject.SESSIONMANAGERURI_NS] = session.get(172 'sessionManagerURI')173 157 request.resource[Resource.URI_NS] = resourceURI 174 158 … … 304 288 305 289 306 class NdgPIPMiddlewareError(Exception):307 """Base class for Policy Information Point WSGI middleware exception types308 """309 310 class NdgPIPMiddlewareConfigError(NdgPIPMiddlewareError):311 """Configuration related error for Policy Information Point WSGI middleware312 """313 314 class NdgPIPMiddleware(PIP, NDGSecurityMiddlewareBase):315 '''Extend Policy Information Point to enable caching of credentials in316 a NDGCredentialWallet object held in beaker.session317 '''318 ENVIRON_KEYNAME = 'ndg.security.server.wsgi.authz.NdgPIPMiddleware'319 320 propertyDefaults = {321 'sessionKey': 'beaker.session.ndg.security',322 }323 propertyDefaults.update(NDGSecurityMiddlewareBase.propertyDefaults)324 325 def __init__(self, app, global_conf, prefix='', **local_conf):326 '''327 @type app: callable following WSGI interface328 @param app: next middleware application in the chain329 @type global_conf: dict330 @param global_conf: PasteDeploy global configuration dictionary331 @type prefix: basestring332 @param prefix: prefix for configuration items333 @type local_conf: dict334 @param local_conf: PasteDeploy application specific configuration335 dictionary336 '''337 338 # Pre-process list items splitting as needed339 if isinstance(local_conf.get('caCertFilePathList'), basestring):340 local_conf[341 'caCertFilePathList'] = NDGSecurityMiddlewareBase.parseListItem(342 local_conf['caCertFilePathList'])343 344 if isinstance(local_conf.get('sslCACertFilePathList'), basestring):345 local_conf[346 'sslCACertFilePathList'347 ] = NDGSecurityMiddlewareBase.parseListItem(348 local_conf['sslCACertFilePathList'])349 350 PIP.__init__(self, prefix=prefix, **local_conf)351 352 for k in local_conf.keys():353 if k.startswith(prefix):354 del local_conf[k]355 356 NDGSecurityMiddlewareBase.__init__(self,357 app,358 global_conf,359 prefix=prefix,360 **local_conf)361 362 def __call__(self, environ, start_response):363 """Take a copy of the session object so that it is in scope for364 _getAttributeCertificate call and add this instance to the environ365 so that the PEPFilter can retrieve it and pass on to the PDP366 367 @type environ: dict368 @param environ: WSGI environment variables dictionary369 @type start_response: function370 @param start_response: standard WSGI start response function371 @rtype: iterable372 @return: response373 """374 self.session = environ.get(self.sessionKey)375 if self.session is None:376 raise NdgPIPMiddlewareConfigError('No beaker session key "%s" found '377 'in environ' % self.sessionKey)378 environ[NdgPIPMiddleware.ENVIRON_KEYNAME] = self379 380 return self._app(environ, start_response)381 382 def _getAttributeCertificate(self, attributeAuthorityURI, **kw):383 '''Extend base class implementation to make use of the384 NDGCredentialWallet Attribute Certificate cache held in the beaker385 session. If no suitable certificate is present invoke default behaviour386 and retrieve an Attribute Certificate from the Attribute Authority or387 Session Manager specified388 389 @type attributeAuthorityURI: basestring390 @param attributeAuthorityURI: URI to Attribute Authority service391 @type username: basestring392 @param username: subject user identifier - could be an OpenID393 @type sessionId: basestring394 @param sessionId: Session Manager session handle395 @type sessionManagerURI: basestring396 @param sessionManagerURI: URI to remote session manager service397 @rtype: ndg.security.common.AttCert.AttCert398 @return: Attribute Certificate containing user roles399 '''400 # Check for a wallet in the current session - if not present, create401 # one. See ndg.security.server.wsgi.authn.SessionHandlerMiddleware402 # for session keys. The 'credentialWallet' key is deleted along with403 # any other security keys when the user logs out404 if not 'credentialWallet' in self.session:405 log.debug("NdgPIPMiddleware._getAttributeCertificate: adding a "406 "Credential Wallet to user session [%s] ...",407 self.session['username'])408 409 self.session['credentialWallet'] = NDGCredentialWallet(410 userId=self.session['username'])411 self.session.save()412 413 # Take reference to wallet for efficiency414 credentialWallet = self.session['credentialWallet']415 416 # Check for existing credentials cached in wallet417 credentialItem = credentialWallet.credentialsKeyedByURI.get(418 attributeAuthorityURI)419 if credentialItem is not None:420 log.debug("NdgPIPMiddleware._getAttributeCertificate: retrieved "421 "existing Attribute Certificate cached in Credential "422 "Wallet for user session [%s]",423 self.session['username'])424 425 # Existing cached credential found - skip call to remote Session426 # Manager / Attribute Authority and return this certificate instead427 return credentialItem.credential428 else:429 attrCert = PIP._getAttributeCertificate(self,430 attributeAuthorityURI,431 **kw)432 433 log.debug("NdgPIPMiddleware._getAttributeCertificate: updating "434 "Credential Wallet with retrieved Attribute "435 "Certificate for user session [%s]",436 self.session['username'])437 438 # Update the wallet with this Attribute Certificate so that it's439 # cached for future calls440 credentialWallet.addCredential(attrCert,441 attributeAuthorityURI=attributeAuthorityURI)442 443 return attrCert444 445 446 290 class SamlPIPMiddlewareError(Exception): 447 291 """Base class for SAML based Policy Information Point WSGI middleware … … 450 294 451 295 452 class SamlPIPMiddlewareConfigError(NdgPIPMiddlewareError): 453 """Configuration related error for Policy Information Point WSGI middleware 296 class SamlPIPMiddlewareConfigError(SamlPIPMiddlewareError): 297 """Configuration related error for SAML Policy Information Point WSGI 298 middleware 454 299 """ 455 300 … … 730 575 731 576 super(AuthorizationMiddlewareBase, self).__init__(app, {}) 732 733 734 class NDGAuthorizationMiddleware(AuthorizationMiddlewareBase):735 """Implementation of AuthorizationMiddlewareBase using the NDG Policy736 Information Point interface. This retrieves attributes over the SOAP/WSDL737 Attribute Authority interface738 (ndg.security.server.wsgi.attributeauthority.AttributeAuthoritySOAPBindingMiddleware)739 and caches NDG Attribute Certificates in an740 ndg.security.common.credentialWallet.NDGCredentialWallet741 """742 PIP_MIDDLEWARE_CLASS = NdgPIPMiddleware743 744 745 class AuthorizationMiddleware(NDGAuthorizationMiddleware):746 """Include this class for backwards compatibility - see warning message747 in FUTURE_DEPRECATION_WARNING_MSG class variable"""748 FUTURE_DEPRECATION_WARNING_MSG = (749 "AuthorizationMiddleware will be deprecated in future releases. "750 "NDGAuthorizationMiddleware is a drop in replacement but should be "751 "replaced with SAMLAuthorizationMiddleware instead")752 753 def __init__(self, *arg, **kw):754 warnings.warn(AuthorizationMiddleware.FUTURE_DEPRECATION_WARNING_MSG,755 PendingDeprecationWarning)756 log.warning(AuthorizationMiddleware.FUTURE_DEPRECATION_WARNING_MSG)757 super(AuthorizationMiddleware, self).__init__(*arg, **kw)758 577 759 578 -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/openid/provider/__init__.py
r6673 r6788 180 180 APPROVED_FLAG_SESSION_KEYNAME = 'approved' 181 181 LAST_CHECKID_REQUEST_SESSION_KEYNAME = 'lastCheckIDRequest' 182 OID_RESPONSE_SESSION_KEYNAME = 'oidResponse' 183 182 184 PARAM_PREFIX = 'openid.provider.' 183 185 … … 217 219 self.__trustedRelyingParties = () 218 220 self.__axResponse = None 219 220 # See _createResponse method221 self.__oidResponse = None222 221 223 222 opt = OpenIDProviderMiddleware.defOpt.copy() … … 1450 1449 1451 1450 def getOidResponse(self): 1452 return self.__oidResponse 1451 return self.__session.get( 1452 OpenIDProviderMiddleware.OID_RESPONSE_SESSION_KEYNAME) 1453 1453 1454 1454 def getSregResponse(self): … … 1472 1472 '"oidResponse" attribute; got %r' % 1473 1473 type(value)) 1474 self.__oidResponse = value 1474 self.__session[OpenIDProviderMiddleware.OID_RESPONSE_SESSION_KEYNAME 1475 ] = value 1475 1476 1476 1477 def setSregResponse(self, value): -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/session.py
r6605 r6788 86 86 SIGNOUT_PATH_PARAMNAME = 'signoutPath' 87 87 SESSION_KEY_PARAMNAME = 'sessionKey' 88 DEFAULT_LOGOUT_RETURN2URI_PARAMNAME = 'defaultLogoutReturnToURI' 89 88 90 propertyDefaults = { 89 91 SIGNOUT_PATH_PARAMNAME: None, 90 SESSION_KEY_PARAMNAME: 'beaker.session.ndg.security' 92 SESSION_KEY_PARAMNAME: 'beaker.session.ndg.security', 93 DEFAULT_LOGOUT_RETURN2URI_PARAMNAME: '/' 91 94 } 92 95 … … 94 97 95 98 LOGOUT_RETURN2URI_ARGNAME = 'ndg.security.logout.r' 99 LOGOUT_REDIRECT_STATUS_CODE = 302 96 100 97 101 PARAM_PREFIX = 'sessionHandler.' … … 109 113 dictionary 110 114 ''' 111 signoutPathParamName = prefix + \112 SessionHandlerMiddleware.SIGNOUT_PATH_PARAMNAME115 cls = SessionHandlerMiddleware 116 signoutPathParamName = prefix + cls.SIGNOUT_PATH_PARAMNAME 113 117 114 118 if signoutPathParamName not in app_conf: 115 119 authKitSignOutPath = app_conf.get( 116 SessionHandlerMiddleware.AUTHKIT_COOKIE_SIGNOUT_PARAMNAME)120 cls.AUTHKIT_COOKIE_SIGNOUT_PARAMNAME) 117 121 118 122 if authKitSignOutPath: … … 120 124 121 125 log.info('Set signoutPath=%s from "%s" setting', 122 authKitSignOutPath,123 SessionHandlerMiddleware.AUTHKIT_COOKIE_SIGNOUT_PARAMNAME)126 authKitSignOutPath, 127 cls.AUTHKIT_COOKIE_SIGNOUT_PARAMNAME) 124 128 else: 125 129 raise SessionHandlerMiddlewareConfigError( 126 130 '"signoutPath" parameter is not set') 127 131 132 defaultLogoutReturnToURIParamName = prefix + \ 133 cls.DEFAULT_LOGOUT_RETURN2URI_PARAMNAME 134 135 self.__defaultLogoutReturnToURI = app_conf.get( 136 defaultLogoutReturnToURIParamName, 137 cls.propertyDefaults[cls.DEFAULT_LOGOUT_RETURN2URI_PARAMNAME]) 138 128 139 super(SessionHandlerMiddleware, self).__init__(app, 129 140 global_conf, … … 184 195 session.save() 185 196 197 186 198 if self.__class__.LOGOUT_RETURN2URI_ARGNAME in environ['QUERY_STRING']: 187 199 params = dict(parse_querystring(environ)) … … 191 203 self.__class__.LOGOUT_RETURN2URI_ARGNAME, '') 192 204 referrer = urllib.unquote(quotedReferrer) 205 206 log.debug('Set redirect URI following logout based on %r URI query ' 207 'string = %r', 208 self.__class__.LOGOUT_RETURN2URI_ARGNAME, 209 referrer) 193 210 else: 194 211 referrer = environ.get('HTTP_REFERER') 195 196 if referrer is not None: 197 def _start_response(status, header, exc_info=None): 198 """Alter the header to send a redirect to the logout 199 referrer address""" 200 filteredHeader = [(field, val) for field, val in header 201 if field.lower() != 'location'] 202 filteredHeader.extend([('Location', referrer)]) 203 return start_response(self.getStatusMessage(302), 204 filteredHeader, 205 exc_info) 206 207 return _start_response 208 else: 209 log.error('No referrer set for redirect following logout') 210 return start_response 212 if referrer is None: 213 log.warning('No HTTP return to URI set for redirect following ' 214 'logout, either via the return to query string %r ' 215 'or the "HTTP_REFERER" environment variable: ' 216 'redirecting based on the %r config file option = ' 217 '%r', 218 self.__class__.LOGOUT_RETURN2URI_ARGNAME, 219 self.__class__.DEFAULT_LOGOUT_RETURN2URI_PARAMNAME, 220 self.__defaultLogoutReturnToURI) 221 222 referrer = self.__defaultLogoutReturnToURI 223 else: 224 log.debug('Set redirect URI following logout based on ' 225 '"HTTP_REFERER" environment variable = %r', 226 referrer) 227 228 def _start_response(status, header, exc_info=None): 229 """Alter the header to send a redirect to the logout referrer 230 address""" 231 232 # Filter out any existing location field setting 233 filteredHeader = [(field, val) for field, val in header 234 if field.lower() != 'location'] 235 236 # Add redirect destination to new location field setting 237 filteredHeader.extend([('Location', referrer)]) 238 239 statusMsg = self.getStatusMessage( 240 self.__class__.LOGOUT_REDIRECT_STATUS_CODE) 241 242 return start_response(statusMsg, filteredHeader, exc_info) 243 244 return _start_response 211 245 212 246 def _setSession(self, environ, session): -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/integration/__init__.py
r6276 r6788 20 20 "/test_403": "test_403", 21 21 "/test_securedURI": "test_securedURI", 22 "/test_accessDeniedToSecuredURI": "test_accessDeniedToSecuredURI" 22 "/test_accessDeniedToSecuredURI": "test_accessDeniedToSecuredURI", 23 "/logout?ndg.security.logout.r=/test_logoutWithReturn2QueryArg": 24 "test_logoutWithReturn2QueryArg", 25 "/test_logoutWithReturn2QueryArg": "test_logoutWithReturn2QueryArg" 23 26 } 24 27 header = """ <h1>Authorisation Integration Tests:</h1> … … 196 199 ('Content-length', str(len(response)))]) 197 200 return response 198 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 UIR 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 199 222 @classmethod 200 223 def app_factory(cls, globalConfig, **localConfig): -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/integration/authz_lite/policy.xml
r6063 r6788 8 8 <Attribute> 9 9 <Name>urn:siteA:security:authz:1.0:attr:staff</Name> 10 <AttributeAuthorityURI>https://localhost:7443/AttributeAuthority /saml</AttributeAuthorityURI>10 <AttributeAuthorityURI>https://localhost:7443/AttributeAuthority</AttributeAuthorityURI> 11 11 </Attribute> 12 12 </Attributes> … … 17 17 <Attribute> 18 18 <Name>urn:siteA:security:authz:1.0:attr:forbidden</Name> 19 <AttributeAuthorityURI>https://localhost:7443/AttributeAuthority /saml</AttributeAuthorityURI>19 <AttributeAuthorityURI>https://localhost:7443/AttributeAuthority</AttributeAuthorityURI> 20 20 </Attribute> 21 21 <Attribute> 22 22 <Name>urn:siteA:security:authz:1.0:attr:keepout</Name> 23 <AttributeAuthorityURI>https://localhost:7443/AttributeAuthority /saml</AttributeAuthorityURI>23 <AttributeAuthorityURI>https://localhost:7443/AttributeAuthority</AttributeAuthorityURI> 24 24 </Attribute> 25 25 </Attributes> -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/integration/authz_lite/securedapp.ini
r6605 r6788 49 49 beaker.session.data_dir = %(here)s/authn/beaker/sessions 50 50 51 beaker.session.cookie_domain = .localhost51 #beaker.session.cookie_domain = .localhost 52 52 53 53 [filter:AuthenticationFilter] … … 57 57 # Set redirect for OpenID Relying Party in the Security Services app instance 58 58 authN.redirectURI = https://localhost:7443/verify 59 # Test with an SSL endpoint 60 #authN.redirectURI = https://localhost/verify 59 60 # Default URI to return to if middleware wasn't able to set via HTTP_REFERER or 61 # passed return to query argument 62 authN.sessionHandler.defaultLogoutReturnToURI = https://localhost:7443/ 61 63 62 64 # AuthKit Set-up … … 74 76 75 77 #authkit.cookie.params.expires = 2 76 authkit.cookie.params.domain = .localhost78 #authkit.cookie.params.domain = .localhost 77 79 78 80 # environ key name for beaker session -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/integration/authz_lite/securityservices.ini
r6615 r6788 25 25 26 26 # Global Attribute Authority Settings 27 attributeAuthorityEnvironKeyName = ndg.security.server.attributeauthority.AttributeAuthority28 27 attributeQueryInterfaceEnvironKeyName = ndg.security.server.attributeauthority.attributeQueryInterface 29 28 … … 56 55 # Ordering of filters and app is critical 57 56 [pipeline:main] 58 pipeline = wsseSignatureVerificationFilter 59 AttributeAuthorityFilter 60 AttributeAuthorityWsdlSoapBindingFilter 61 wsseSignatureFilter 57 pipeline = AttributeAuthorityFilter 62 58 AttributeAuthoritySamlSoapBindingFilter 63 59 SessionMiddlewareFilter … … 82 78 beaker.session.cookie_expires = True 83 79 84 beaker.session.cookie_domain = .localhost80 #beaker.session.cookie_domain = .localhost 85 81 86 82 # Key name for keying into environ dictionary … … 104 100 cookie.includeip = False 105 101 106 cookie.params.domain = .localhost102 #cookie.params.domain = .localhost 107 103 108 104 # SSL Client Certificate based authentication is invoked if the client passed … … 164 160 authkit.cookie.secret=9wvZObs9anUEhSIAnJNoY2iJq59FfYZr 165 161 authkit.cookie.signoutpath = /logout 166 authkit.cookie.params.domain = .localhost162 #authkit.cookie.params.domain = .localhost 167 163 168 164 # Disable inclusion of client IP address from cookie signature due to … … 334 330 prefix = attributeAuthority. 335 331 336 # Key name by which the WSDL SOAP based interface may reference this337 # service338 attributeAuthority.environKeyName = %(attributeAuthorityEnvironKeyName)s339 340 # Key name for the SAML SOAP binding based interface to reference this341 # service's attribute query method342 attributeAuthority.environKeyNameAttributeQueryInterface: %(attributeQueryInterfaceEnvironKeyName)s343 344 # Attribute Authority settings345 # 'name' setting MUST agree with map config file 'thisHost' name attribute346 attributeAuthority.name: Site A347 348 332 # Lifetime is measured in seconds 349 attributeAuthority.attCertLifetime: 28800 350 351 # Allow an offset for clock skew between servers running 352 # security services. NB, measured in seconds - use a minus sign for time in the 353 # past 354 attributeAuthority.attCertNotBeforeOff: 0 355 356 # All Attribute Certificates issued are recorded in this dir 357 attributeAuthority.attCertDir: %(testConfigDir)s/attributeauthority/sitea/attributeCertificateLog 358 359 # Files in attCertDir are stored using a rotating file handler 360 # attCertFileLogCnt sets the max number of files created before the first is 361 # overwritten 362 attributeAuthority.attCertFileName: ac.xml 363 attributeAuthority.attCertFileLogCnt: 16 364 attributeAuthority.dnSeparator:/ 365 366 # Location of role mapping file 367 attributeAuthority.mapConfigFilePath: %(testConfigDir)s/attributeauthority/sitea/siteAMapConfig.xml 333 attributeAuthority.assertionLifetime: 28800 368 334 369 335 # Settings for custom AttributeInterface derived class to get user roles for given … … 373 339 #attributeAuthority.attributeInterface.className: TestUserRoles 374 340 341 # Key name for the SAML SOAP binding based interface to reference this 342 # service's attribute query method 343 attributeAuthority.environKeyNameAttributeQueryInterface: %(attributeQueryInterfaceEnvironKeyName)s 344 375 345 # SQLAlchemy Attribute Interface 376 346 attributeAuthority.attributeInterface.connectionString: %(dbConnectionString)s 377 attributeAuthority.attributeInterface.modName: ndg.security.server.attributeauthority 378 attributeAuthority.attributeInterface.className: SQLAlchemyAttributeInterface 379 attributeAuthority.attributeInterface.issuerName = /O=Site A/CN=Attribute Authority 347 attributeAuthority.attributeInterface.className: ndg.security.server.attributeauthority.SQLAlchemyAttributeInterface 380 348 attributeAuthority.attributeInterface.samlSubjectSqlQuery = select count(*) from users where openid = '${userId}' 381 349 attributeAuthority.attributeInterface.samlAttribute2SqlQuery.1 = "urn:esg:first:name" "select firstname from users where openid = '${userId}'" … … 387 355 /CN=test/O=NDG/OU=BADC 388 356 389 # Config for XML signature of Attribute Certificate390 attributeAuthority.signingPriKeyFilePath: %(testConfigDir)s/attributeauthority/sitea/siteA-aa.key391 attributeAuthority.signingCertFilePath: %(testConfigDir)s/attributeauthority/sitea/siteA-aa.crt392 attributeAuthority.caCertFilePathList: %(testConfigDir)s/ca/ndg-test-ca.crt393 394 395 # SOAP WSDL Based Binding to the Attribute Authority396 [filter:AttributeAuthorityWsdlSoapBindingFilter]397 paste.filter_app_factory = ndg.security.server.wsgi.attributeauthority:AttributeAuthoritySOAPBindingMiddleware.filter_app_factory398 prefix = service.soap.binding.399 attributeAuthoritySOAPBindingPrefix = attributeauthority.service.soap.binding.400 401 service.soap.binding.referencedFilters = filter:wsseSignatureVerificationFilter402 service.soap.binding.path = /AttributeAuthority403 service.soap.binding.enableWSDLQuery = True404 service.soap.binding.charset = utf-8405 service.soap.binding.serviceSOAPBindingEnvironKeyName = ndg.security.server.wsgi.attributeauthority.AttributeAuthoritySOAPBindingMiddleware406 407 attributeauthority.service.soap.binding.attributeAuthorityEnvironKeyName = %(attributeAuthorityEnvironKeyName)s408 attributeauthority.service.soap.binding.wsseSignatureVerificationFilterID = filter:wsseSignatureVerificationFilter409 410 411 357 # SAML SOAP Binding to the Attribute Authority 412 358 [filter:AttributeAuthoritySamlSoapBindingFilter] … … 419 365 saml.soapbinding.serialise = ndg.security.common.saml_utils.esg.xml.etree:EsgResponseElementTree.toXML 420 366 421 saml.soapbinding.pathMatchList = /AttributeAuthority /saml367 saml.soapbinding.pathMatchList = /AttributeAuthority 422 368 saml.soapbinding.queryInterfaceKeyName = %(attributeQueryInterfaceEnvironKeyName)s 423 369 424 425 #______________________________________________________________________________ 426 # WS-Security Signature Verification 427 [filter:wsseSignatureVerificationFilter] 428 paste.filter_app_factory = ndg.security.server.wsgi.wssecurity:SignatureVerificationFilter.filter_app_factory 429 filterID = %(__name__)s 430 431 # Settings for WS-Security SignatureHandler class used by this filter 432 wsseCfgFilePrefix = wssecurity 433 434 # Verify against known CAs - Provide a space separated list of file paths 435 wssecurity.caCertFilePathList=%(testConfigDir)s/ca/ndg-test-ca.crt 436 437 438 #______________________________________________________________________________ 439 # Apply WS-Security Signature 440 [filter:wsseSignatureFilter] 441 paste.filter_app_factory = ndg.security.server.wsgi.wssecurity:ApplySignatureFilter.filter_app_factory 442 443 # Reference the verification filter in order to be able to apply signature 444 # confirmation 445 referencedFilters = filter:wsseSignatureVerificationFilter 446 wsseSignatureVerificationFilterID = filter:wsseSignatureVerificationFilter 447 448 # Last filter in chain of SOAP handlers writes the response 449 writeResponse = True 450 451 # Settings for WS-Security SignatureHandler class used by this filter 452 wsseCfgFilePrefix = wssecurity 453 454 # Certificate associated with private key used to sign a message. The sign 455 # method will add this to the BinarySecurityToken element of the WSSE header. 456 wssecurity.signingCertFilePath=%(testConfigDir)s/pki/wsse-server.crt 457 458 # PEM encoded private key file 459 wssecurity.signingPriKeyFilePath=%(testConfigDir)s/pki/wsse-server.key 460 461 # Set the ValueType for the BinarySecurityToken added to the WSSE header for a 462 # signed message. See __setReqBinSecTokValType method and binSecTokValType 463 # class variable for options - it may be one of X509, X509v3, X509PKIPathv1 or 464 # give full namespace to alternative - see 465 # ZSI.wstools.Namespaces.OASIS.X509TOKEN 466 # 467 # binSecTokValType determines whether signingCert or signingCertChain 468 # attributes will be used. 469 wssecurity.reqBinSecTokValType=X509v3 470 471 # Add a timestamp element to an outbound message 472 wssecurity.addTimestamp=True 473 474 # For WSSE 1.1 - service returns signature confirmation containing signature 475 # value sent by client 476 wssecurity.applySignatureConfirmation=True 370 # Clock skew for SAML Attribute Queries - allow clockSkew number of seconds 371 # tolerance for query issueInstant parameter. Set here to 3 minutes 372 saml.soapbinding.clockSkewTolerance: 180.0 373 374 saml.soapbinding.issuer: /O=Site A/CN=Attribute Authority 375 477 376 478 377 # Logging configuration -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/__init__.py
r6721 r6788 68 68 SITEA_SSL_ATTRIBUTEAUTHORITY_PORTNUM = 5443 69 69 SITEA_SSL_ATTRIBUTEAUTHORITY_SAML_URI = \ 70 'https://localhost:%d/AttributeAuthority /saml' % \70 'https://localhost:%d/AttributeAuthority' % \ 71 71 SITEA_SSL_ATTRIBUTEAUTHORITY_PORTNUM 72 72 SSL_CERT_DN = "/C=UK/ST=Oxfordshire/O=BADC/OU=Security/CN=localhost" -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/wsgi/authz/README
r6062 r6788 2 2 ======================================== 3 3 These tests call ndg.security.server.wsgi.authz.SAMLAuthorizationMiddleware 4 and ndg.security.server.wsgi.authz.NDGAuthorizationMiddleware via 5 paste.fixture. An attribute authority service needs to be running in order 6 for the middleware to check user attributes, In a separate terminal start 7 this service: 4 via paste.fixture. An attribute authority service is also started as a separate 5 thread. 8 6 9 $ python ../../../config/attributeauthority/sitea/siteAServerApp.py 10 11 Then, to run the tests: 7 To run the tests: 12 8 13 9 $ python test_authz.py 14 10 15 P J Kershaw 22/0 5/0911 P J Kershaw 22/03/10 -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/wsgi/authz/pep-result-handler-test.ini
r6284 r6788 32 32 # If omitted, DN of SSL Cert is used 33 33 pip.attributeQuery.issuerName = 34 pip.attributeQuery.clockSkew = 0.34 pip.attributeQuery.clockSkewTolerance = 0. 35 35 pip.attributeQuery.queryAttributes.0 = urn:siteA:security:authz:1.0:attr, , http://www.w3.org/2001/XMLSchema#string 36 36 pip.attributeQuery.sslCACertDir=%(testConfigDir)s/ca -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/wsgi/authz/saml-policy.xml
r6062 r6788 9 9 <Name>urn:siteA:security:authz:1.0:attr:staff</Name> 10 10 <!-- Endpoint is for SOAP/SAML based ESG Interface --> 11 <AttributeAuthorityURI>https://localhost:5443/AttributeAuthority /saml</AttributeAuthorityURI>11 <AttributeAuthorityURI>https://localhost:5443/AttributeAuthority</AttributeAuthorityURI> 12 12 </Attribute> 13 13 </Attributes> … … 18 18 <Attribute> 19 19 <Name>urn:siteA:security:authz:1.0:attr:forbidden</Name> 20 <AttributeAuthorityURI>https://localhost:5443/AttributeAuthority /saml</AttributeAuthorityURI>20 <AttributeAuthorityURI>https://localhost:5443/AttributeAuthority</AttributeAuthorityURI> 21 21 </Attribute> 22 22 <Attribute> 23 23 <Name>urn:siteA:security:authz:1.0:attr:keepout</Name> 24 <AttributeAuthorityURI>https://localhost:5443/AttributeAuthority /saml</AttributeAuthorityURI>24 <AttributeAuthorityURI>https://localhost:5443/AttributeAuthority</AttributeAuthorityURI> 25 25 </Attribute> 26 26 </Attributes> … … 35 35 <Attribute> 36 36 <Name>urn:siteA:security:authz:1.0:attr:admin</Name> 37 <AttributeAuthorityURI>https://localhost:5443/AttributeAuthority /saml</AttributeAuthorityURI>37 <AttributeAuthorityURI>https://localhost:5443/AttributeAuthority</AttributeAuthorityURI> 38 38 </Attribute> 39 39 </Attributes> -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/wsgi/authz/saml-test.ini
r6062 r6788 31 31 # If omitted, DN of SSL Cert is used 32 32 pip.attributeQuery.issuerName = 33 pip.attributeQuery.clockSkew = 0.33 pip.attributeQuery.clockSkewTolerance = 0. 34 34 pip.attributeQuery.queryAttributes.0 = urn:siteA:security:authz:1.0:attr, , http://www.w3.org/2001/XMLSchema#string 35 35 pip.attributeQuery.sslCACertDir=%(testConfigDir)s/ca -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/wsgi/authz/test_authz.py
r6284 r6788 32 32 from ndg.security.server.wsgi.authz.result_handler.redirect import \ 33 33 HTTPRedirectPEPResultHandlerMiddleware 34 from ndg.security.server.wsgi.authz import (NdgPIPMiddlewareConfigError, 35 SamlPIPMiddlewareConfigError) 34 from ndg.security.server.wsgi.authz import SamlPIPMiddlewareConfigError 36 35 from ndg.security.common.authz.msi import Response 37 36 … … 98 97 def save(self): 99 98 pass 99 100 101 class TestAuthZMiddleware(object): 102 '''Test Application for the Authentication handler to protect''' 103 response = "Test Authorization application" 104 105 def __init__(self, app_conf, **local_conf): 106 pass 107 108 def __call__(self, environ, start_response): 109 110 if environ['PATH_INFO'] == '/test_401': 111 status = "401 Unauthorized" 112 113 elif environ['PATH_INFO'] == '/test_403': 114 status = "403 Forbidden" 115 116 elif environ['PATH_INFO'] == '/test_200': 117 status = "200 OK" 118 119 elif environ['PATH_INFO'] == '/test_accessDeniedToSecuredURI': 120 # Nb. AuthZ middleware should intercept the request and bypass this 121 # response 122 status = "200 OK" 123 124 elif environ['PATH_INFO'] == '/test_accessGrantedToSecuredURI': 125 status = "200 OK" 126 else: 127 status = "404 Not found" 128 129 start_response(status, 130 [('Content-length', 131 str(len(TestAuthZMiddleware.response))), 132 ('Content-type', 'text/plain')]) 133 return [TestAuthZMiddleware.response] 134 135 136 class BeakerSessionStub(dict): 137 """Emulate beaker.session session object for purposes of the unit tests 138 """ 139 def save(self): 140 pass 100 141 101 142 102 class NdgWSGIAuthZTestCase(BaseTestCase):103 INI_FILE = ' ndg-test.ini'143 class SamlWSGIAuthZTestCase(BaseTestCase): 144 INI_FILE = 'saml-test.ini' 104 145 THIS_DIR = os.path.dirname(os.path.abspath(__file__)) 105 def __init__(self, *args, **kwargs): 146 def __init__(self, *args, **kwargs): 106 147 BaseTestCase.__init__(self, *args, **kwargs) 107 108 109 wsgiapp = loadapp('config:'+ NdgWSGIAuthZTestCase.INI_FILE,110 relative_to= NdgWSGIAuthZTestCase.THIS_DIR)148 149 150 wsgiapp = loadapp('config:'+SamlWSGIAuthZTestCase.INI_FILE, 151 relative_to=SamlWSGIAuthZTestCase.THIS_DIR) 111 152 self.app = paste.fixture.TestApp(wsgiapp) 112 153 113 self.startSiteAAttributeAuthority() 114 154 self.startSiteAAttributeAuthority(withSSL=True, 155 port=SamlWSGIAuthZTestCase.SITEA_SSL_ATTRIBUTEAUTHORITY_PORTNUM) 156 157 115 158 def test01CatchNoBeakerSessionFound(self): 116 159 … … 119 162 try: 120 163 response = self.app.get('/test_200') 121 except NdgPIPMiddlewareConfigError, e:164 except SamlPIPMiddlewareConfigError, e: 122 165 print("ok - expected: %s exception: %s" % (e.__class__, e)) 123 166 … … 138 181 # even though a user is set in the session 139 182 140 extra_environ={'beaker.session.ndg.security': 141 BeakerSessionStub(username='testuser')} 183 extra_environ = { 184 'beaker.session.ndg.security': 185 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI) 186 } 142 187 response = self.app.get('/test_401', 143 188 extra_environ=extra_environ, … … 150 195 # even though a user is set in the session 151 196 152 extra_environ={'beaker.session.ndg.security': 153 BeakerSessionStub(username='testuser')} 197 extra_environ = { 198 'beaker.session.ndg.security': 199 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI) 200 } 154 201 response = self.app.get('/test_403', 155 202 extra_environ=extra_environ, … … 172 219 # User is logged in but doesn't have the required credentials for 173 220 # access 174 extra_environ={'beaker.session.ndg.security': 175 BeakerSessionStub(username='testuser')} 221 extra_environ = { 222 'beaker.session.ndg.security': 223 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI) 224 } 176 225 177 226 response = self.app.get('/test_accessDeniedToSecuredURI', 178 227 extra_environ=extra_environ, 179 228 status=403) 229 print response 180 230 self.assert_("Insufficient privileges to access the " 181 231 "resource" in response) 182 print response183 232 184 233 def test07AccessGrantedForSecuredURI(self): … … 186 235 # User is logged in and has credentials for access to a URI secured 187 236 # by the policy file 188 extra_environ={'beaker.session.ndg.security': 189 BeakerSessionStub(username='testuser')} 237 extra_environ = { 238 'beaker.session.ndg.security': 239 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI) 240 } 190 241 191 242 response = self.app.get('/test_accessGrantedToSecuredURI', … … 199 250 # User is logged in but doesn't have the required credentials for 200 251 # access 201 extra_environ={'beaker.session.ndg.security': 202 BeakerSessionStub(username='testuser')} 252 extra_environ = { 253 'beaker.session.ndg.security': 254 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI) 255 } 203 256 204 257 # Try this URI with the query arg admin=1. This will be picked up … … 219 272 print response 220 273 221 222 class TestAuthZMiddleware(object):223 '''Test Application for the Authentication handler to protect'''224 response = "Test Authorization application"225 226 def __init__(self, app_conf, **local_conf):227 pass228 229 def __call__(self, environ, start_response):230 231 if environ['PATH_INFO'] == '/test_401':232 status = "401 Unauthorized"233 234 elif environ['PATH_INFO'] == '/test_403':235 status = "403 Forbidden"236 237 elif environ['PATH_INFO'] == '/test_200':238 status = "200 OK"239 240 elif environ['PATH_INFO'] == '/test_accessDeniedToSecuredURI':241 # Nb. AuthZ middleware should intercept the request and bypass this242 # response243 status = "200 OK"244 245 elif environ['PATH_INFO'] == '/test_accessGrantedToSecuredURI':246 status = "200 OK"247 else:248 status = "404 Not found"249 250 start_response(status,251 [('Content-length',252 str(len(TestAuthZMiddleware.response))),253 ('Content-type', 'text/plain')])254 return [TestAuthZMiddleware.response]255 256 257 class BeakerSessionStub(dict):258 """Emulate beaker.session session object for purposes of the unit tests259 """260 def save(self):261 pass262 263 264 class SamlWSGIAuthZTestCase(BaseTestCase):265 INI_FILE = 'saml-test.ini'266 THIS_DIR = os.path.dirname(os.path.abspath(__file__))267 def __init__(self, *args, **kwargs):268 BaseTestCase.__init__(self, *args, **kwargs)269 270 271 wsgiapp = loadapp('config:'+SamlWSGIAuthZTestCase.INI_FILE,272 relative_to=SamlWSGIAuthZTestCase.THIS_DIR)273 self.app = paste.fixture.TestApp(wsgiapp)274 275 self.startSiteAAttributeAuthority(withSSL=True,276 port=SamlWSGIAuthZTestCase.SITEA_SSL_ATTRIBUTEAUTHORITY_PORTNUM)277 278 279 def test01CatchNoBeakerSessionFound(self):280 281 # PEPFilterConfigError is raised if no beaker.session is set in282 # environ283 try:284 response = self.app.get('/test_200')285 except SamlPIPMiddlewareConfigError, e:286 print("ok - expected: %s exception: %s" % (e.__class__, e))287 288 def test02Ensure200WithNotLoggedInAndUnsecuredURI(self):289 290 # Check the authZ middleware leaves the response alone if the URI291 # is not matched in the policy292 293 # Simulate a beaker.session in the environ294 extra_environ={'beaker.session.ndg.security':BeakerSessionStub()}295 response = self.app.get('/test_200',296 extra_environ=extra_environ)297 298 def test03Catch401WithLoggedIn(self):299 300 # Check that the application being secured can raise a HTTP 401301 # response and that this respected by the Authorization middleware302 # even though a user is set in the session303 304 extra_environ = {305 'beaker.session.ndg.security':306 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI)307 }308 response = self.app.get('/test_401',309 extra_environ=extra_environ,310 status=401)311 312 def test04Catch403WithLoggedIn(self):313 314 # Check that the application being secured can raise a HTTP 403315 # response and that this respected by the Authorization middleware316 # even though a user is set in the session317 318 extra_environ = {319 'beaker.session.ndg.security':320 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI)321 }322 response = self.app.get('/test_403',323 extra_environ=extra_environ,324 status=403)325 326 def test05Catch401WithNotLoggedInAndSecuredURI(self):327 328 # AuthZ middleware grants access because the URI requested is not329 # targeted in the policy330 331 # AuthZ middleware checks for username key in session set by AuthN332 # handler333 extra_environ={'beaker.session.ndg.security':BeakerSessionStub()}334 response = self.app.get('/test_accessDeniedToSecuredURI',335 extra_environ=extra_environ,336 status=401)337 338 def test06AccessDeniedForSecuredURI(self):339 340 # User is logged in but doesn't have the required credentials for341 # access342 extra_environ = {343 'beaker.session.ndg.security':344 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI)345 }346 347 response = self.app.get('/test_accessDeniedToSecuredURI',348 extra_environ=extra_environ,349 status=403)350 self.assert_("Insufficient privileges to access the "351 "resource" in response)352 print response353 354 def test07AccessGrantedForSecuredURI(self):355 356 # User is logged in and has credentials for access to a URI secured357 # by the policy file358 extra_environ = {359 'beaker.session.ndg.security':360 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI)361 }362 363 response = self.app.get('/test_accessGrantedToSecuredURI',364 extra_environ=extra_environ,365 status=200)366 self.assert_(TestAuthZMiddleware.response in response)367 print response368 369 def test08AccessDeniedForAdminQueryArg(self):370 371 # User is logged in but doesn't have the required credentials for372 # access373 extra_environ = {374 'beaker.session.ndg.security':375 BeakerSessionStub(username=SamlWSGIAuthZTestCase.OPENID_URI)376 }377 378 # Try this URI with the query arg admin=1. This will be picked up379 # by the policy as a request requiring admin rights. The request is380 # denied as the user doesn't have these rights but this then calls381 # into play the PEP result handler defined in this module,382 # RedirectFollowingAccessDenied. This class reinvokes the request383 # but without the admin query argument. Access is then granted for384 # the redirected request385 response = self.app.get('/test_accessGrantedToSecuredURI',386 params={'admin': 1},387 extra_environ=extra_environ,388 status=302)389 try:390 redirectResponse = response.follow(extra_environ=extra_environ)391 except paste.fixture.AppError, e:392 self.failIf(TestAuthZMiddleware.response not in response)393 print response394 395 274 396 275 class PEPResultHandlerTestCase(BaseTestCase):
Note: See TracChangeset
for help on using the changeset viewer.