Changeset 7357
- Timestamp:
- 23/08/10 16:32:14 (11 years ago)
- Location:
- TI12-security/trunk/NDGSecurity/python
- Files:
-
- 6 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/credentialwallet.py
r6730 r7357 32 32 """Generic Exception class for CredentialWallet module. Overrides 33 33 Exception to enable writing to the log""" 34 def __init__(self, *arg, **kw):35 if len(arg) > 0:36 log.error(arg[0])37 38 Exception.__init__(self, *arg, **kw)39 34 40 35 … … 43 38 to enable writing to the log""" 44 39 45 46 class CredentialWalletAttributeRequestDenied(CredentialWalletError):47 """Handling exception where CredentialWallet is denied authorisation by an48 Attribute Authority.49 50 @type __extAttCertList: list51 @ivar __extAttCertList: list of candidate Attribute Certificates that52 could be used to try to get a mapped certificate from the target53 Attribute Authority54 55 @type __trustedHostInfo: dict56 @ivar __trustedHostInfo: dictionary indexed by host name giving57 details of Attribute Authority URI and roles for trusted hosts"""58 59 def __init__(self, *args, **kw):60 """Raise exception for attribute request denied with option to give61 caller hint to certificates that could used to try to obtain a62 mapped certificate63 64 @type extAttCertList: list65 @param extAttCertList: list of candidate Attribute Certificates that66 could be used to try to get a mapped certificate from the target67 Attribute Authority68 69 @type trustedHostInfo: dict70 @param trustedHostInfo: dictionary indexed by host name giving71 details of Attribute Authority URI and roles for trusted hosts"""72 73 self.__trustedHostInfo = kw.pop('trustedHostInfo', {})74 self.__extAttCertList = kw.pop('extAttCertList', [])75 76 CredentialWalletError.__init__(self, *args, **kw)77 78 def _getTrustedHostInfo(self):79 """Get message text"""80 return self.__trustedHostInfo81 82 trustedHostInfo = property(fget=_getTrustedHostInfo,83 doc="URI and roles details for trusted hosts")84 85 def _getExtAttCertList(self):86 """Return list of candidate Attribute Certificates that could be used87 to try to get a mapped certificate from the target Attribute Authority88 """89 return self.__extAttCertList90 91 extAttCertList = property(fget=_getExtAttCertList,92 doc="list of candidate Attribute Certificates "93 "that could be used to try to get a mapped "94 "certificate from the target Attribute "95 "Authority")96 97 40 98 41 class _MetaCredentialWallet(type): … … 118 61 119 62 accessGranted = property(fget=_getAccessGranted) 63 120 64 121 65 class CredentialContainer(object): … … 124 68 ITEM_ATTRNAME = 'credential' 125 69 ISSUERNAME_ATTRNAME = 'issuerName' 126 ATTRIBUTE_AUTHORITY_URI_ATTRNAME = 'attributeAuthorityURI'127 70 CREDENTIAL_TYPE_ATTRNAME = 'type' 128 71 … … 131 74 ITEM_ATTRNAME, 132 75 ISSUERNAME_ATTRNAME, 133 ATTRIBUTE_AUTHORITY_URI_ATTRNAME,134 76 CREDENTIAL_TYPE_ATTRNAME 135 77 ) 136 78 __slots__ = tuple(["__%s" % n for n in __ATTRIBUTE_NAMES]) 79 del n 137 80 138 81 def __init__(self, _type=None): … … 143 86 self.__credential = None 144 87 self.__issuerName = None 145 self.__attributeAuthorityURI = None146 88 147 89 def _getType(self): … … 199 141 _setIssuerName, 200 142 doc="Name of issuer of the credential") 201 202 def _getAttributeAuthorityURI(self):203 return self.__attributeAuthorityURI204 205 def _setAttributeAuthorityURI(self, value):206 """String or None type are allowed - The URI may be set to None if207 a local Attribute Authority instance is being invoked rather208 one hosted via a remote URI209 """210 if not isinstance(value, (basestring, type(None))):211 raise TypeError('Expecting string or None type for '212 '"attributeAuthorityURI"; got %r instead' %213 type(value))214 self.__attributeAuthorityURI = value215 216 attributeAuthorityURI = property(_getAttributeAuthorityURI,217 _setAttributeAuthorityURI,218 doc="Attribute Authority Service URI")219 143 220 144 def __getstate__(self): … … 235 159 236 160 class CredentialWalletBase(object): 237 """Abstract base class for NDG and SAMLCredential Wallet implementations161 """Abstract base class for Credential Wallet implementations 238 162 """ 239 163 CONFIG_FILE_OPTNAMES = ("userId", ) 240 __slots__ = ("__credentials", "__ credentialsKeyedByURI", "__userId")164 __slots__ = ("__credentials", "__userId") 241 165 242 166 def __init__(self): 243 167 self.__userId = None 244 168 self.__credentials = {} 245 self.__credentialsKeyedByURI = {}246 169 247 170 @classmethod … … 250 173 @type cfg: basestring /ConfigParser derived type 251 174 @param cfg: configuration file path or ConfigParser type object 252 @rtype: ndg.security.common.credentialWallet.SAML CredentialWallet175 @rtype: ndg.security.common.credentialWallet.SAMLAssertionWallet 253 176 @return: new instance of this class 254 177 ''' … … 272 195 def addCredential(self, 273 196 credential, 274 attributeAuthorityURI=None,197 issuerEndpoint=None, 275 198 bUpdateCredentialRepository=True): 276 199 """Add a new attribute certificate to the list of credentials held. … … 279 202 SAML assertion 280 203 @param credential: new attribute Certificate to be added 281 @type attributeAuthorityURI: basestring282 @param attributeAuthorityURI: input the Attribute Authority URIfrom204 @type issuerEndpoint: basestring 205 @param issuerEndpoint: input the URI of issuing service from 283 206 which credential was retrieved. This is added to a dict to enable 284 access to a given Attribute Certificate keyed by Attribute Authority207 access to a given Attribute Certificate keyed by issuing service 285 208 URI. See the getCredential method. 286 209 @type bUpdateCredentialRepository: bool … … 321 244 doc="List of credentials linked to issuing " 322 245 "authorities") 323 324 def _getCredentialsKeyedByURI(self):325 """Get Property method for credentials keyed by Attribute Authority URI326 Credentials dict is read-only but also see addCredential method327 328 @rtype: dict329 @return: cached ACs indexed by issuing Attribute Authority"""330 return self.__credentialsKeyedByURI331 332 # Publish attribute333 credentialsKeyedByURI = property(fget=_getCredentialsKeyedByURI,334 doc="List of Attribute Certificates "335 "linked to attribute authority URI")336 246 337 247 def _getUserId(self): … … 366 276 367 277 368 class SAMLCredentialWallet(CredentialWalletBase): 369 """CredentialWallet for Earth System Grid supporting caching of SAML 370 Attribute Assertions 278 class SAMLAssertionWallet(CredentialWalletBase): 279 """Wallet for Earth System Grid supporting caching of SAML Assertions 371 280 """ 372 281 CONFIG_FILE_OPTNAMES = CredentialWalletBase.CONFIG_FILE_OPTNAMES + ( 373 282 "clockSkewTolerance", ) 374 283 __slots__ = ("__clockSkewTolerance",) 375 376 CREDENTIAL_REPOSITORY_NOT_SUPPORTED_MSG = ("SAMLCredentialWallet doesn't "377 "support the "378 "CredentialRepository "379 "interface")380 284 381 285 def __init__(self): 382 super(SAML CredentialWallet, self).__init__()286 super(SAMLAssertionWallet, self).__init__() 383 287 self.__clockSkewTolerance = timedelta(seconds=0.) 384 288 385 289 def _getClockSkewTolerance(self): 386 290 return self.__clockSkewTolerance … … 430 334 431 335 setattr(self, optName, val) 432 433 def addCredential(self,434 credential,435 attributeAuthorityURI=None,436 bUpdateCredentialRepository=False,437 verifyCredential=True):438 """Add a new assertion to the list of assertion credentials held.439 440 @type credential: SAML assertion441 @param credential: new assertion to be added442 @type attributeAuthorityURI: basestring443 @param attributeAuthorityURI: input the Attribute Authority URI from444 which credential was retrieved. This is added to a dict to enable445 access to a given Attribute Certificate keyed by Attribute Authority446 URI. See the getCredential method.447 @type bUpdateCredentialRepository: bool448 @param bUpdateCredentialRepository: if set to True, and a repository449 exists it will be updated with the new credentials also. Nb. a derived450 class will need to be implemented to enable this capability - see451 the updateCredentialRepository method.452 @type verifyCredential: bool453 @param verifyCredential: if set to True, test validity of credential454 by calling isValidCredential method.455 456 @rtype: bool457 @return: True if credential was added otherwise False. - If an458 existing certificate from the same issuer has a later expiry it will459 take precedence and the new input certificate is ignored."""460 461 # Check input462 if not isinstance(credential, Assertion):463 raise CredentialWalletError("Input credential must be an "464 "%r type object" % Assertion)465 466 if verifyCredential and not self.isValidCredential(credential):467 raise CredentialWalletError("Validity time error with assertion %r"468 % credential)469 470 # Check to see if there is an existing Attribute Certificate held471 # that was issued by the same host. If so, compare the expiry time.472 # The one with the latest expiry will be retained and the other473 # ignored474 bUpdateCred = True475 if credential.issuer is None:476 raise AttributeError("Adding SAML assertion to wallet: no issuer "477 "set")478 479 issuerName = credential.issuer.value480 481 if issuerName in self.credentials:482 # There is an existing certificate held with the same issuing483 # host name as the new certificate484 credentialOld = self.credentials[issuerName].credential485 486 # If the new certificate has an earlier expiry time then ignore it487 bUpdateCred = (credential.conditions.notOnOrAfter >488 credentialOld.conditions.notOnOrAfter)489 490 if bUpdateCred:491 thisCredential = CredentialContainer(Assertion)492 thisCredential.credential = credential493 thisCredential.issuerName = issuerName494 thisCredential.attributeAuthorityURI = attributeAuthorityURI495 496 self.credentials[issuerName] = thisCredential497 498 if attributeAuthorityURI:499 self.credentialsKeyedByURI[500 attributeAuthorityURI] = thisCredential501 502 # Update the Credentials Repository - the permanent store of user503 # authorisation credentials. This allows credentials for previous504 # sessions to be re-instated505 if bUpdateCredentialRepository:506 self.updateCredentialRepository()507 508 # Flag to caller to indicate whether the input certificate was added509 # to the credentials or an exsiting certificate from the same issuer510 # took precedence511 return bUpdateCred512 336 513 337 def audit(self): … … 515 339 expired or are otherwise invalid.""" 516 340 517 log.debug("SAML CredentialWallet.audit ...")341 log.debug("SAMLAssertionWallet.audit ...") 518 342 519 343 for issuerName, issuerEntry in self.credentials.items(): 520 344 if not self.isValidCredential(issuerEntry.credential): 521 self.credentialsKeyedByURI.pop(522 issuerEntry.attributeAuthorityURI,523 None)524 525 345 del self.credentials[issuerName] 526 527 def updateCredentialRepository(self, auditCred=True):528 """No Credential Repository support is required"""529 msg = SAMLCredentialWallet.CREDENTIAL_REPOSITORY_NOT_SUPPORTED_MSG530 log.warning(msg)531 warnings.warn(msg)532 346 533 347 def isValidCredential(self, assertion): … … 559 373 def __getstate__(self): 560 374 '''Enable pickling for use with beaker.session''' 561 _dict = super(SAML CredentialWallet, self).__getstate__()562 563 for attrName in SAML CredentialWallet.__slots__:375 _dict = super(SAMLAssertionWallet, self).__getstate__() 376 377 for attrName in SAMLAssertionWallet.__slots__: 564 378 # Ugly hack to allow for derived classes setting private member 565 379 # variables 566 380 if attrName.startswith('__'): 567 attrName = "_SAML CredentialWallet" + attrName381 attrName = "_SAMLAssertionWallet" + attrName 568 382 569 383 _dict[attrName] = getattr(self, attrName) 570 384 571 385 return _dict 386 387 388 class SAMLAttributeWallet(SAMLAssertionWallet): 389 """Wallet with functionality for retrieving assertions containing attribute 390 statements based on endpoint URI and issuer name 391 """ 392 __slots__ = ("__credentialsKeyedByURI",) 393 394 def __init__(self): 395 super(SAMLAttributeWallet, self).__init__() 396 self.__credentialsKeyedByURI = {} 397 398 def _getCredentialsKeyedByURI(self): 399 """Get Property method for credentials keyed by issuing service URI 400 Credentials dict is read-only but also see addCredential method 401 402 @rtype: dict 403 @return: cached ACs indexed by issuing service URI""" 404 return self.__credentialsKeyedByURI 405 406 # Publish attribute 407 credentialsKeyedByURI = property(fget=_getCredentialsKeyedByURI, 408 doc="List of credentials " 409 "linked to issuing service URI") 410 411 def addCredential(self, 412 credential, 413 issuerEndpoint=None, 414 verifyCredential=True): 415 """Add a new assertion to the list of assertion credentials held. 416 417 @type credential: SAML assertion 418 @param credential: new assertion to be added 419 @type issuerEndpoint: basestring 420 @param issuerEndpoint: input the issuing service URI from 421 which credential was retrieved. This is added to a dict to enable 422 access to a given Attribute Certificate keyed by issuing service 423 URI. See the getCredential method. 424 @type verifyCredential: bool 425 @param verifyCredential: if set to True, test validity of credential 426 by calling isValidCredential method. 427 428 @rtype: bool 429 @return: True if credential was added otherwise False. - If an 430 existing certificate from the same issuer has a later expiry it will 431 take precedence and the new input certificate is ignored.""" 432 433 # Check input 434 if not isinstance(credential, Assertion): 435 raise CredentialWalletError("Input credential must be an " 436 "%r type object" % Assertion) 437 438 if verifyCredential and not self.isValidCredential(credential): 439 raise CredentialWalletError("Validity time error with assertion %r" 440 % credential) 441 442 # Check to see if there is an existing Attribute Certificate held 443 # that was issued by the same host. If so, compare the expiry time. 444 # The one with the latest expiry will be retained and the other 445 # ignored 446 bUpdateCred = True 447 if credential.issuer is None: 448 raise AttributeError("Adding SAML assertion to wallet: no issuer " 449 "set") 450 451 issuerName = credential.issuer.value 452 453 if issuerName in self.credentials: 454 # There is an existing certificate held with the same issuing 455 # host name as the new certificate 456 credentialOld = self.credentials[issuerName].credential 457 458 # If the new certificate has an earlier expiry time then ignore it 459 bUpdateCred = (credential.conditions.notOnOrAfter > 460 credentialOld.conditions.notOnOrAfter) 461 462 if bUpdateCred: 463 thisCredential = CredentialContainer(Assertion) 464 thisCredential.credential = credential 465 thisCredential.issuerName = issuerName 466 467 self.credentials[issuerName] = thisCredential 468 469 if issuerEndpoint: 470 self.credentialsKeyedByURI[ 471 issuerEndpoint] = thisCredential 472 473 def audit(self): 474 """Check the credentials held in the wallet removing any that have 475 expired or are otherwise invalid.""" 476 477 log.debug("SAMLAssertionWallet.audit ...") 478 479 for issuerName, issuerEntry in self.credentials.items(): 480 if not self.isValidCredential(issuerEntry.credential): 481 foundMatch = False 482 endpoint = None 483 for endpoint, v in self.credentialsKeyedByURI.items(): 484 if v.issuerName.value == issuerName: 485 foundMatch = True 486 break 487 488 if foundMatch: 489 self.credentialsKeyedByURI.pop(endpoint, None) 490 491 del self.credentials[issuerName] 492 493 def __getstate__(self): 494 '''Enable pickling for use with beaker.session''' 495 _dict = super(SAMLAttributeWallet, self).__getstate__() 496 497 for attrName in SAMLAttributeWallet.__slots__: 498 # Ugly hack to allow for derived classes setting private member 499 # variables 500 if attrName.startswith('__'): 501 attrName = "_SAMLAttributeWallet" + attrName 502 503 _dict[attrName] = getattr(self, attrName) 504 505 return _dict 506 507 508 class SAMLAuthzDecisionWallet(SAMLAssertionWallet): 509 """Wallet with functionality for retrieving assertions containing 510 authorisation decision statements. Credentials are keyed by resource Id""" 511 __slots__ = () 512 513 def addCredential(self, assertion, verifyCredential=True): 514 """Add a new assertion to the list of assertion credentials held. 515 516 @type assertion: SAML assertion 517 @param assertion: new assertion to be added 518 @type verifyCredential: bool 519 @param verifyCredential: if set to True, test validity of credential 520 by calling isValidCredential method. 521 522 @rtype: bool 523 @return: True if credential was added otherwise False. - If an 524 existing certificate from the same issuer has a later expiry it will 525 take precedence and the new input certificate is ignored.""" 526 527 # Check input 528 if not isinstance(assertion, Assertion): 529 raise CredentialWalletError("Input assertion must be an " 530 "%r type object" % Assertion) 531 532 if verifyCredential and not self.isValidCredential(assertion): 533 raise CredentialWalletError("Validity time error with assertion %r" 534 % assertion) 535 536 # Check to see if there is an existing decision statement held for the 537 # same resource ID. If so, compare the expiry time. The one with the 538 # latest expiry will be retained and the other ignored 539 bUpdateCred = True 540 541 # Get the resource ID from the authorisation decision statement 542 # Nb. Assumes a SINGLE statement 543 if len(assertion.authzDecisionStatements) != 1: 544 raise CredentialWalletError("Expecting a single authorisation " 545 "decision statement passed with the " 546 "input assertion; found %r", 547 len(assertion.authzDecisionStatements)) 548 549 resourceId = assertion.authzDecisionStatements[0].resource 550 if resourceId in self.credentials: 551 # There is an existing certificate held with the same issuing 552 # host name as the new certificate 553 assertionOld = self.credentials[resourceId].credential 554 555 # If the new certificate has an earlier expiry time then ignore it 556 bUpdateCred = (assertion.conditions.notOnOrAfter > 557 assertionOld.conditions.notOnOrAfter) 558 559 if bUpdateCred: 560 thisCredential = CredentialContainer(Assertion) 561 thisCredential.credential = assertion 562 563 if assertion.issuer.value: 564 thisCredential.issuerName = assertion.issuer.value 565 566 self.credentials[resourceId] = thisCredential 567 568 def __getstate__(self): 569 '''Enable pickling for use with beaker.session''' 570 _dict = super(SAMLAuthzDecisionWallet, self).__getstate__() 571 572 for attrName in SAMLAuthzDecisionWallet.__slots__: 573 # Ugly hack to allow for derived classes setting private member 574 # variables 575 if attrName.startswith('__'): 576 attrName = "_SAMLAuthzDecisionWallet" + attrName 577 578 _dict[attrName] = getattr(self, attrName) 579 580 return _dict 572 581 573 582 -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/authz/__init__.py
r7287 r7357 22 22 23 23 from ndg.security.common.utils.classfactory import importClass 24 from ndg.security.common.credentialwallet import SAML CredentialWallet24 from ndg.security.common.credentialwallet import SAMLAttributeWallet 25 25 from ndg.security.server.wsgi import NDGSecurityMiddlewareBase 26 26 from ndg.security.server.wsgi.authz.pep import SamlPepFilter -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/authz/pep.py
r7287 r7357 21 21 from ndg.security.server.wsgi.session import (SessionMiddlewareBase, 22 22 SessionHandlerMiddleware) 23 from ndg.security.common.credentialwallet import SAMLAuthzDecisionWallet 24 from ndg.security.common.utils import str2Bool 23 25 24 26 … … 45 47 AUTHZ_DECISION_QUERY_PARAMS_PREFIX = 'authzDecisionQuery.' 46 48 SESSION_KEY_PARAM_NAME = 'sessionKey' 49 CACHE_DECISIONS_PARAM_NAME = 'cacheDecisions' 47 50 48 51 CREDENTIAL_WALLET_SESSION_KEYNAME = \ … … 53 56 PARAM_NAMES = ( 54 57 'authzServiceURI', 55 'sessionKey' 58 'sessionKey', 59 'cacheDecisions' 56 60 ) 57 61 __slots__ = ( … … 70 74 self.__authzServiceURI = None 71 75 self.__sessionKey = None 76 self.__cacheDecisions = False 72 77 73 78 def _getClient(self): … … 116 121 doc="environ key name for Beaker session object") 117 122 123 def _getCacheDecisions(self): 124 return self.__cacheDecisions 125 126 def _setCacheDecisions(self, value): 127 if isinstance(value, basestring): 128 self.__cacheDecisions = str2Bool(value) 129 elif isinstance(value, bool): 130 self.__cacheDecisions = value 131 else: 132 raise TypeError('Expecting bool/string type for "cacheDecisions" ' 133 'attribute; got %r' % type(value)) 134 135 cacheDecisions = property(_getCacheDecisions, _setCacheDecisions, 136 doc="Set to True to make the session cache " 137 "authorisation decisions returned from the " 138 "Authorisation Service") 139 118 140 def initialise(self, prefix='', **kw): 119 141 '''Initialise object from keyword settings … … 135 157 value = kw.get(paramName) 136 158 if value is None: 137 raise SamlPepFilterConfigError('Missing option %r' % 138 paramName)159 raise SamlPepFilterConfigError('Missing option %r' % paramName) 160 139 161 setattr(self, name, value) 140 162 … … 177 199 178 200 request = webob.Request(environ) 179 self.client.resourceURI = request.url 180 181 # Nb. user may not be logged in hence REMOTE_USER is not set 182 self.client.subjectID = request.remote_user or '' 183 184 samlAuthzResponse = self.client.send(uri=self.__authzServiceURI) 185 186 # Record the result in the user's session to enable later 187 # interrogation by any result handler Middleware 188 self.setSession(self.client.query, samlAuthzResponse) 201 202 # Check for cached decision 203 if self.cacheDecisions: 204 cachedAssertion = self._retrieveAuthzDecision(request.url) 205 else: 206 cachedAssertion = None 207 208 if cachedAssertion is not None: 209 assertions = (cachedAssertion,) 210 else: 211 # No stored decision in cache, invoke the authorisation service 212 self.client.resourceURI = request.url 213 214 # Nb. user may not be logged in hence REMOTE_USER is not set 215 self.client.subjectID = request.remote_user or '' 216 217 samlAuthzResponse = self.client.send(uri=self.__authzServiceURI) 218 assertions = samlAuthzResponse.assertions 219 220 # Record the result in the user's session to enable later 221 # interrogation by any result handler Middleware 222 self.setSession(self.client.query, samlAuthzResponse) 223 189 224 190 225 # Set HTTP 403 Forbidden response if any of the decisions returned are … … 192 227 failDecisions = (DecisionType.DENY, DecisionType.INDETERMINATE) 193 228 194 for assertion in samlAuthzResponse.assertions: 229 # Review decision statement(s) in assertions and enforce the decision 230 assertion = None 231 for assertion in assertions: 195 232 for authzDecisionStatement in assertion.authzDecisionStatements: 196 233 if authzDecisionStatement.decision.value in failDecisions: … … 211 248 return response(environ, start_response) 212 249 250 if assertion is None: 251 log.error("No assertions set in authorisation decision response " 252 "from %r", self.authzServiceURI) 253 254 response.body = ('An error occurred retrieving an access decision ' 255 'for %r for user %r' % ( 256 self.client.resourceURI, 257 self.client.subjectID)) 258 response.content_type = 'text/plain' 259 log.info(response.body) 260 return response(environ, start_response) 261 262 if self.cacheDecisions: 263 self._cacheAuthzDecision(assertion) 264 213 265 # If got through to here then all is well, call next WSGI middleware/app 214 266 return self._app(environ, start_response) 215 267 268 def _retrieveAuthzDecision(self, resourceId): 269 """Return assertion containing authorisation decision for the given 270 resource ID. 271 272 @param resourceId: search for decisions for this resource Id 273 @type resourceId: basestring 274 @return: assertion containing authorisation decision for the given 275 resource ID or None if no wallet has been set or no assertion was 276 found matching the input resource Id 277 @rtype: ndg.saml.saml2.core.Assertion / None type 278 """ 279 # Get reference to wallet 280 walletKeyName = self.__class__.CREDENTIAL_WALLET_SESSION_KEYNAME 281 credWallet = self.session.get(walletKeyName) 282 283 # Wallet has a dictionary of credential objects keyed by resource ID 284 credentials = getattr(credWallet, 'credentials', {}) 285 286 # Retrieve assertion from Credential object 287 assertion = getattr(credentials.get(resourceId), 'credential', None) 288 return assertion 289 290 291 def _cacheAuthzDecision(self, assertion): 292 """Cache an authorisation decision from a response retrieved from the 293 authorisation service. This is invoked only if cacheDecisions boolean 294 is set to True 295 296 @param assertion: SAML assertion containing authorisation decision 297 @type assertion: ndg.saml.saml2.core.Assertion 298 """ 299 walletKeyName = self.__class__.CREDENTIAL_WALLET_SESSION_KEYNAME 300 credWallet = self.session.get(walletKeyName) 301 if credWallet is None: 302 credWallet = SAMLAuthzDecisionWallet() 303 304 credWallet.addCredential(assertion) 305 self.session[walletKeyName] = credWallet 306 self.session.save() 307 216 308 def setSession(self, request, response, save=True): 217 309 """Set PEP context information in the Beaker session using standard key 218 names 310 names. This is a snapshot of the last request and the response 311 received. It can be used by downstream middleware to provide contextual 312 information about authorisation decisions 219 313 220 314 @param session: beaker session -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/xacml/ctx_handler/saml_ctx_handler.py
r7350 r7357 232 232 return None 233 233 else: 234 return self.__issuerProxy. value234 return self.__issuerProxy.format 235 235 236 236 def _setIssuerFormat(self, value): … … 461 461 assertion.version = SAMLVersion(SAMLVersion.VERSION_20) 462 462 assertion.id = str(uuid4()) 463 464 assertion.issuer = _saml.Issuer() 465 assertion.issuer.value = self.issuerName 466 assertion.issuer.format = self.issuerFormat 463 467 464 468 now = datetime.utcnow() -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/xacml/pip/saml_pip.py
r7350 r7357 234 234 @return: attribute values found for query subject or None if none 235 235 could be found 236 @raise PIPConfigException: if attribute ID -> Attribute Authority mapping is237 empty236 @raise PIPConfigException: if attribute ID -> Attribute Authority 237 mapping is empty 238 238 """ 239 239 … … 275 275 if attribute.attributeId == self.subjectAttributeId: 276 276 if len(attribute.attributeValues) != 1: 277 raise Exception("Expecting a single attribute value " 278 "for query subject ID") 277 raise PIPRequestCtxException("Expecting a single " 278 "attribute value " 279 "for query subject ID") 279 280 subjectId = attribute.attributeValues[0].value 280 281 break … … 294 295 # query 295 296 attributeFormat = attributeDesignator.dataType 297 attributeId = attributeDesignator.attributeId 298 296 299 samlAttribute = SamlAttribute() 297 300 samlAttribute.name = attributeDesignator.attributeId … … 321 324 # format specified and copy into XACML attributes 322 325 xacmlAttribute = XacmlAttribute() 323 xacmlAttribute.attributeId = attribute Designator.attributeId326 xacmlAttribute.attributeId = attributeId 324 327 xacmlAttribute.dataType = attributeFormat 325 328 … … 342 345 343 346 # Update the XACML request context subject with the new attributes 344 xacmlCtxSubject.attributes.append(xacmlAttribute) 347 matchFound = False 348 for attr in xacmlCtxSubject.attributes: 349 matchFound = attr.attributeId == attributeId 350 if matchFound: 351 newAttrVals = [attrVal 352 for attrVal in xacmlAttribute.attributeValues 353 if attrVal not in attr.attributeValues] 354 attr.attributeValues.extend(newAttrVals) 355 break 356 357 if not matchFound: 358 xacmlCtxSubject.attributes.append(xacmlAttribute) 345 359 346 360 # Return the attributes to the caller to comply with the interface -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/config/authorisationservice/policy.xml
r7350 r7357 165 165 AttributeId="urn:siteA:security:authz:1.0:attr" 166 166 DataType="http://www.w3.org/2001/XMLSchema#string"/> 167 <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string"> urn:siteA:security:authz:1.0:attr:admin</AttributeValue>167 <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue> 168 168 </SubjectMatch> 169 169 </Subject> -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/integration/__init__.py
r7350 r7357 23 23 "/logout?ndg.security.logout.r=/test_logoutWithReturn2QueryArg": 24 24 "test_logoutWithReturn2QueryArg", 25 "/test_logout WithReturn2QueryArg": "test_logoutWithReturn2QueryArg"25 "/test_logoutViaHttpReferrer": "test_logoutViaHttpReferrer" 26 26 } 27 27 header = """ <h1>Authorisation Integration Tests:</h1> … … 88 88 </html> 89 89 """ % (AuthZTestApp.header, 90 '\n'.join(['<li><a href="%s">%s</a></li>' % (link, link)90 '\n'.join(['<li><a href="%s">%s</a></li>' % (link, name) 91 91 for link,name in self.method.items() if name != 'default']) 92 92 ) … … 220 220 return response 221 221 222 def test_logoutViaHttpReferrer(self, environ, start_response): 223 """Test logout - the middleware works out where to return to by checking 224 the HTTP_REFERER environ setting 225 """ 226 response = """<html> 227 <head/> 228 <body> 229 <h1>Logged Out</h1> 230 <p>Successfully redirected to specified return to HTTP_REFERER=%s 231 following logout. 232 <a href="/">Return to tests</a></p> 233 </body> 234 </html> 235 """ % environ['PATH_INFO'] 236 237 start_response('200 OK', 238 [('Content-type', 'text/html'), 239 ('Content-length', str(len(response)))]) 240 return response 241 222 242 @classmethod 223 243 def app_factory(cls, globalConfig, **localConfig): -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/integration/full_system/policy.xml
r7350 r7357 37 37 Policy element above 38 38 --> 39 <Rule RuleId="Graphics and CSS" Effect="Permit"> 40 <!-- 41 Public access for graphics and CSS content 42 --> 43 <Target> 44 <Resources> 45 <Resource> 46 <ResourceMatch MatchId="urn:oasis:names:tc:xacml:2.0:function:anyURI-regexp-match"> 47 <ResourceAttributeDesignator 48 AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" 49 DataType="http://www.w3.org/2001/XMLSchema#anyURI"/> 50 <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#anyURI">^http://localhost:7080/layout/</AttributeValue> 51 </ResourceMatch> 52 </Resource> 53 </Resources> 54 </Target> 55 </Rule> 56 39 57 <Rule RuleId="urn:ndg:security:public-uri" Effect="Permit"> 40 58 <!-- … … 51 69 AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" 52 70 DataType="http://www.w3.org/2001/XMLSchema#anyURI"/> 53 <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#anyURI">^http://localhost:7080/(test_401|test_403|test_logout WithReturn2QueryArg)?$</AttributeValue>71 <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#anyURI">^http://localhost:7080/(test_401|test_403|test_logoutViaHttpReferrer|test_logoutWithReturn2QueryArg)?$</AttributeValue> 54 72 </ResourceMatch> 55 73 </Resource> -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/integration/full_system/securedapp.ini
r7350 r7357 95 95 pep.sessionKey = beaker.session.ndg.security 96 96 pep.authzServiceURI = https://localhost:7443/AuthorisationService 97 pep.cacheDecisions = True 97 98 98 99 # Settings for Policy Information Point used by the Policy Decision Point to
Note: See TracChangeset
for help on using the changeset viewer.