1 | """NDG Security MSI Resource Policy module |
---|
2 | |
---|
3 | NERC Data Grid Project |
---|
4 | """ |
---|
5 | __author__ = "P J Kershaw" |
---|
6 | __date__ = "03/04/09" |
---|
7 | __copyright__ = "(C) 2009 Science and Technology Facilities Council" |
---|
8 | __contact__ = "Philip.Kershaw@stfc.ac.uk" |
---|
9 | __license__ = "BSD - see LICENSE file in top-level directory" |
---|
10 | __contact__ = "Philip.Kershaw@stfc.ac.uk" |
---|
11 | __revision__ = "$Id$" |
---|
12 | |
---|
13 | import logging |
---|
14 | log = logging.getLogger(__name__) |
---|
15 | from elementtree import ElementTree |
---|
16 | |
---|
17 | # For parsing: ElementTree helpers |
---|
18 | getNs = lambda elem: elem.tag.split('}')[0][1:] |
---|
19 | getLocalName = lambda elem: elem.tag.rsplit('}', 1)[ - 1] |
---|
20 | |
---|
21 | class PolicyParseError(Exception): |
---|
22 | """Error reading policy attributes from file""" |
---|
23 | |
---|
24 | class Policy(object): |
---|
25 | def __init__(self, policyFilePath=None): |
---|
26 | self.policyFilePath = policyFilePath |
---|
27 | self.description = None |
---|
28 | self.targets = [] |
---|
29 | |
---|
30 | def parse(self): |
---|
31 | """Parse the policy file set in policyFilePath attribute |
---|
32 | """ |
---|
33 | elem = ElementTree.parse(self.policyFilePath) |
---|
34 | root = elem.getroot() |
---|
35 | |
---|
36 | for elem in root: |
---|
37 | localName = getLocalName(elem) |
---|
38 | if localName == "Description": |
---|
39 | self.description = elem.text.strip() |
---|
40 | |
---|
41 | elif localName == "Target": |
---|
42 | self.targets.append(Target.Parse(elem)) |
---|
43 | |
---|
44 | else: |
---|
45 | raise PolicyParseError("Invalid policy attribute: %s" % |
---|
46 | localName) |
---|
47 | |
---|
48 | @classmethod |
---|
49 | def Parse(cls, policyFilePath): |
---|
50 | policy = cls(policyFilePath=policyFilePath) |
---|
51 | policy.parse() |
---|
52 | return policy |
---|
53 | |
---|
54 | class TargetParseError(Exception): |
---|
55 | """Error reading resource attributes from file""" |
---|
56 | |
---|
57 | import re |
---|
58 | |
---|
59 | class Target(object): |
---|
60 | """Define access behaviour for a resource match a given URI pattern""" |
---|
61 | def __init__(self): |
---|
62 | self.uriPattern = None |
---|
63 | self.attributes = [] |
---|
64 | self.attributeAuthorityURI = None |
---|
65 | |
---|
66 | def parse(self, root): |
---|
67 | for elem in root: |
---|
68 | localName = getLocalName(elem) |
---|
69 | if localName == "URIPattern": |
---|
70 | self.uriPattern = elem.text.strip() |
---|
71 | self.regEx = re.compile(self.uriPattern) |
---|
72 | |
---|
73 | elif localName == "Attributes": |
---|
74 | for attrElem in elem: |
---|
75 | self.attributes.append(attrElem.text.strip()) |
---|
76 | |
---|
77 | elif localName == "AttributeAuthority": |
---|
78 | # Expecting first element to contain the URI |
---|
79 | self.attributeAuthorityURI = elem[0].text.strip() |
---|
80 | else: |
---|
81 | raise ResourceParseError("Invalid resource attribute: %s" % |
---|
82 | localName) |
---|
83 | |
---|
84 | @classmethod |
---|
85 | def Parse(cls, root): |
---|
86 | resource = cls() |
---|
87 | resource.parse(root) |
---|
88 | return resource |
---|
89 | |
---|
90 | def __str__(self): |
---|
91 | return str(self.uriPattern) |
---|
92 | |
---|
93 | class _AttrDict(dict): |
---|
94 | """Utility class for holding a constrained list of attributes governed |
---|
95 | by a namespace list""" |
---|
96 | namespaces = () |
---|
97 | def __init__(self, **attributes): |
---|
98 | invalidAttributes = [attr for attr in attributes \ |
---|
99 | if attr not in self.__class__.namespaces] |
---|
100 | if len(invalidAttributes) > 0: |
---|
101 | raise TypeError("The following attribute namespace(s) are not " |
---|
102 | "recognised: %s" % invalidAttributes) |
---|
103 | |
---|
104 | self.update(attributes) |
---|
105 | |
---|
106 | def __setitem__(self, key, val): |
---|
107 | if key not in self.__class__.namespaces: |
---|
108 | raise KeyError('Namespace "%s" not recognised. Valid namespaces ' |
---|
109 | 'are: %s' % self.__class__.namespaces) |
---|
110 | |
---|
111 | dict.__setitem__(self, key, val) |
---|
112 | |
---|
113 | |
---|
114 | def update(self, d, **kw): |
---|
115 | for dictArg in (d, kw): |
---|
116 | for k in dictArg: |
---|
117 | if key not in self.__class__.namespaces: |
---|
118 | raise KeyError('Namespace "%s" not recognised. Valid ' |
---|
119 | 'namespaces are: %s' % |
---|
120 | self.__class__.namespaces) |
---|
121 | |
---|
122 | dict.update(self, d, **kw) |
---|
123 | |
---|
124 | class Subject(_AttrDict): |
---|
125 | '''Subject designator''' |
---|
126 | namespaces = ( |
---|
127 | "urn:ndg:security:authz:1.0:attr:subject:userId", |
---|
128 | "urn:ndg:security:authz:1.0:attr:subject:sessionId", |
---|
129 | "urn:ndg:security:authz:1.0:attr:subject:sessionManagerURI", |
---|
130 | "urn:ndg:security:authz:1.0:attr:subject:roles" |
---|
131 | ) |
---|
132 | (USERID_NS, SESSIONID_NS, SESSIONMANAGERURI_NS, ROLES_NS) = namespaces |
---|
133 | |
---|
134 | class Resource(_AttrDict): |
---|
135 | '''Resource designator''' |
---|
136 | namespaces = ( |
---|
137 | "urn:ndg:security:authz:1.0:attr:resource:uri", |
---|
138 | ) |
---|
139 | (URI_NS,) = namespaces |
---|
140 | |
---|
141 | class Request(object): |
---|
142 | '''Request to send to a PDP''' |
---|
143 | def __init__(self, subject=Subject(), resource=Resource()): |
---|
144 | self.subject = subject |
---|
145 | self.resource = resource |
---|
146 | |
---|
147 | class Response(object): |
---|
148 | |
---|
149 | decisionValues = range(4) |
---|
150 | (DECISION_PERMIT, |
---|
151 | DECISION_DENY, |
---|
152 | DECISION_INDETERMINATE, |
---|
153 | DECISION_NOT_APPLICABLE) = decisionValues |
---|
154 | |
---|
155 | # string versions of the 4 Decision types used for encoding |
---|
156 | DECISIONS = ("Permit", "Deny", "Indeterminate", "NotApplicable") |
---|
157 | |
---|
158 | def __init__(self, status, message=None): |
---|
159 | if status not in Response.decisionValues: |
---|
160 | raise TypeError("Status %s not recognised" % status) |
---|
161 | |
---|
162 | self.status = status |
---|
163 | self.message = message |
---|
164 | |
---|
165 | |
---|
166 | from ndg.security.common.AttCert import AttCertInvalidSignature, \ |
---|
167 | AttCertNotBeforeTimeError, AttCertExpired, AttCertError |
---|
168 | |
---|
169 | from ndg.security.common.sessionmanager import SessionManagerClient, \ |
---|
170 | SessionNotFound, SessionCertTimeError, SessionExpired, InvalidSession, \ |
---|
171 | AttributeRequestDenied |
---|
172 | |
---|
173 | from ndg.security.common.attributeauthority import AttributeAuthorityClient, \ |
---|
174 | NoTrustedHosts, NoMatchingRoleInTrustedHosts, \ |
---|
175 | InvalidAttributeAuthorityClientCtx |
---|
176 | from ndg.security.common.attributeauthority import AttributeRequestDenied as \ |
---|
177 | AA_AttributeRequestDenied |
---|
178 | |
---|
179 | from ndg.security.common.authz.pdp import PDPUserNotLoggedIn, \ |
---|
180 | PDPUserAccessDenied |
---|
181 | |
---|
182 | class SubjectRetrievalError(Exception): |
---|
183 | """Generic exception class for errors related to information about the |
---|
184 | subject""" |
---|
185 | |
---|
186 | class InvalidAttributeCertificate(SubjectRetrievalError): |
---|
187 | "The certificate containing authorisation roles is invalid" |
---|
188 | def __init__(self, msg=None): |
---|
189 | SubjectRetrievalError.__init__(self, msg or |
---|
190 | InvalidAttributeCertificate.__doc__) |
---|
191 | |
---|
192 | class AttributeCertificateInvalidSignature(SubjectRetrievalError): |
---|
193 | ("There is a problem with the signature of the certificate containing " |
---|
194 | "authorisation roles") |
---|
195 | def __init__(self, msg=None): |
---|
196 | SubjectRetrievalError.__init__(self, msg or |
---|
197 | AttributeCertificateInvalidSignature.__doc__) |
---|
198 | |
---|
199 | class AttributeCertificateNotBeforeTimeError(SubjectRetrievalError): |
---|
200 | ("There is a time issuing error with certificate containing authorisation " |
---|
201 | "roles") |
---|
202 | def __init__(self, msg=None): |
---|
203 | SubjectRetrievalError.__init__(self, msg or |
---|
204 | AttributeCertificateNotBeforeTimeError.__doc__) |
---|
205 | |
---|
206 | class AttributeCertificateExpired(SubjectRetrievalError): |
---|
207 | "The certificate containing authorisation roles has expired" |
---|
208 | def __init__(self, msg=None): |
---|
209 | SubjectRetrievalError.__init__(self, msg or |
---|
210 | AttributeCertificateExpired.__doc__) |
---|
211 | |
---|
212 | class SessionExpiredMsg(SubjectRetrievalError): |
---|
213 | 'Session has expired. Please re-login at your home organisation' |
---|
214 | def __init__(self, msg=None): |
---|
215 | SubjectRetrievalError.__init__(self, msg or SessionExpiredMsg.__doc__) |
---|
216 | |
---|
217 | class SessionNotFoundMsg(SubjectRetrievalError): |
---|
218 | 'No session was found. Please try re-login with your home organisation' |
---|
219 | def __init__(self, msg=None): |
---|
220 | SubjectRetrievalError.__init__(self, msg or |
---|
221 | SessionNotFoundMsg.__doc__) |
---|
222 | |
---|
223 | class InvalidSessionMsg(SubjectRetrievalError): |
---|
224 | 'Session is invalid. Please try re-login with your home organisation' |
---|
225 | def __init__(self, msg=None): |
---|
226 | SubjectRetrievalError.__init__(self, msg or |
---|
227 | InvalidSessionMsg.__doc__) |
---|
228 | |
---|
229 | class InitSessionCtxError(SubjectRetrievalError): |
---|
230 | 'A problem occurred initialising a session connection' |
---|
231 | def __init__(self, msg=None): |
---|
232 | SubjectRetrievalError.__init__(self, msg or |
---|
233 | InitSessionCtxError.__doc__) |
---|
234 | |
---|
235 | class AttributeCertificateRequestError(SubjectRetrievalError): |
---|
236 | 'A problem occurred requesting a certificate containing authorisation roles' |
---|
237 | def __init__(self, msg=None): |
---|
238 | SubjectRetrievalError.__init__(self, msg or |
---|
239 | AttributeCertificateRequestError.__doc__) |
---|
240 | |
---|
241 | class PIPAttributeQuery(_AttrDict): |
---|
242 | '''Policy Information Point Query class.''' |
---|
243 | namespaces = ( |
---|
244 | "urn:ndg:security:authz:1.0:attr:subject", |
---|
245 | "urn:ndg:security:authz:1.0:attr:attributeAuthorityURI", |
---|
246 | ) |
---|
247 | (SUBJECT_NS, ATTRIBUTEAUTHORITY_NS) = namespaces |
---|
248 | |
---|
249 | class PIPAttributeResponse(dict): |
---|
250 | '''Policy Information Point Response class.''' |
---|
251 | namespaces = ( |
---|
252 | Subject.ROLES_NS, |
---|
253 | ) |
---|
254 | |
---|
255 | |
---|
256 | from ndg.security.common.wssecurity import WSSecurityConfig |
---|
257 | from ndg.security.common.credentialwallet import CredentialWallet |
---|
258 | |
---|
259 | class PIP(object): |
---|
260 | """Policy Information Point - this implementation enables the PDP to |
---|
261 | retrieve attributes about the Subject""" |
---|
262 | |
---|
263 | def __init__(self, prefix='', **cfg): |
---|
264 | '''Set-up WS-Security and SSL settings for connection to an |
---|
265 | Attribute Authority |
---|
266 | |
---|
267 | @type **cfg: dict |
---|
268 | @param **cfg: keywords including 'sslCACertFilePathList' used to set a |
---|
269 | list of CA certificates for an SSL connection to the Attribute |
---|
270 | Authority if used and also WS-Security settings as used by |
---|
271 | ndg.security.common.wssecurity.WSSecurityConfig |
---|
272 | ''' |
---|
273 | self.wssecurityCfg = WSSecurityConfig() |
---|
274 | wssePrefix = prefix + 'wssecurity' |
---|
275 | self.wssecurityCfg.update(cfg, prefix=wssePrefix) |
---|
276 | |
---|
277 | # List of CA certificates used to verify peer certificate with SSL |
---|
278 | # connections to Attribute Authority |
---|
279 | self.sslCACertFilePathList = cfg.get(prefix + 'sslCACertFilePathList', []) |
---|
280 | |
---|
281 | # List of CA certificates used to verify the signatures of |
---|
282 | # Attribute Certificates retrieved |
---|
283 | self.caCertFilePathList = cfg.get(prefix + 'caCertFilePathList', []) |
---|
284 | |
---|
285 | |
---|
286 | def attributeQuery(self, attributeQuery): |
---|
287 | """Query the Attribute Authority specified in the request to retrieve |
---|
288 | the attributes if any corresponding to the subject |
---|
289 | |
---|
290 | @type attributeResponse: PIPAttributeQuery |
---|
291 | @param attributeResponse: |
---|
292 | @rtype: PIPAttributeResponse |
---|
293 | @return: response containing the attributes retrieved from the |
---|
294 | Attribute Authority""" |
---|
295 | |
---|
296 | subject = attributeQuery[PIPAttributeQuery.SUBJECT_NS] |
---|
297 | username = subject[Subject.USERID_NS] |
---|
298 | sessionId = subject[Subject.SESSIONID_NS] |
---|
299 | attributeAuthorityURI = attributeQuery[ |
---|
300 | PIPAttributeQuery.ATTRIBUTEAUTHORITY_NS] |
---|
301 | |
---|
302 | sessionId = subject[Subject.SESSIONID_NS] |
---|
303 | attributeCertificate = self._getAttributeCertificate( |
---|
304 | attributeAuthorityURI, |
---|
305 | username, |
---|
306 | sessionId, |
---|
307 | subject[Subject.SESSIONMANAGERURI_NS]) |
---|
308 | |
---|
309 | attributeResponse = PIPAttributeResponse() |
---|
310 | attributeResponse[Subject.ROLES_NS] = attributeCertificate.roles |
---|
311 | |
---|
312 | return attributeResponse |
---|
313 | |
---|
314 | |
---|
315 | def _getAttributeCertificate(self, |
---|
316 | attributeAuthorityURI, |
---|
317 | username=None, |
---|
318 | sessionId=None, |
---|
319 | sessionManagerURI=None): |
---|
320 | '''Retrieve an Attribute Certificate |
---|
321 | |
---|
322 | @type attributeAuthorityURI: basestring |
---|
323 | @param attributeAuthorityURI: URI to Attribute Authority service |
---|
324 | @type username: basestring |
---|
325 | @param username: subject user identifier - could be an OpenID |
---|
326 | @type sessionId: basestring |
---|
327 | @param sessionId: Session Manager session handle |
---|
328 | @type sessionManagerURI: basestring |
---|
329 | @param sessionManagerURI: URI to remote session manager service |
---|
330 | @rtype: ndg.security.common.AttCert.AttCert |
---|
331 | @return: Attribute Certificate containing user roles |
---|
332 | ''' |
---|
333 | |
---|
334 | if False and sessionId and sessionManagerURI: |
---|
335 | attrCert = self._getAttributeCertificateFromSessionManager( |
---|
336 | attributeAuthorityURI, |
---|
337 | sessionId, |
---|
338 | sessionManagerURI) |
---|
339 | else: |
---|
340 | return self._getAttributeCertificateFromAttributeAuthority( |
---|
341 | attributeAuthorityURI, |
---|
342 | username) |
---|
343 | |
---|
344 | try: |
---|
345 | attrCert.certFilePathList = self.caCertFilePathList |
---|
346 | attrCert.isValid(raiseExcep=True) |
---|
347 | |
---|
348 | except AttCertInvalidSignature, e: |
---|
349 | log.exception(e) |
---|
350 | raise AttributeCertificateInvalidSignature() |
---|
351 | |
---|
352 | except AttCertNotBeforeTimeError, e: |
---|
353 | log.exception(e) |
---|
354 | raise AttributeCertificateNotBeforeTimeError() |
---|
355 | |
---|
356 | except AttCertExpired, e: |
---|
357 | log.exception(e) |
---|
358 | raise AttributeCertificateExpired() |
---|
359 | |
---|
360 | except AttCertError, e: |
---|
361 | log.exception(e) |
---|
362 | raise InvalidAttributeCertificate() |
---|
363 | |
---|
364 | |
---|
365 | def _getAttributeCertificateFromSessionManager(self, |
---|
366 | attributeAuthorityURI, |
---|
367 | sessionId, |
---|
368 | sessionManagerURI): |
---|
369 | '''Retrieve an Attribute Certificate using the subject's Session |
---|
370 | Manager |
---|
371 | |
---|
372 | @type sessionId: basestring |
---|
373 | @param sessionId: Session Manager session handle |
---|
374 | @type sessionManagerURI: basestring |
---|
375 | @param sessionManagerURI: URI to remote session manager service |
---|
376 | @type attributeAuthorityURI: basestring |
---|
377 | @param attributeAuthorityURI: URI to Attribute Authority service |
---|
378 | @rtype: ndg.security.common.AttCert.AttCert |
---|
379 | @return: Attribute Certificate containing user roles |
---|
380 | ''' |
---|
381 | |
---|
382 | try: |
---|
383 | # Create Session Manager client - if a file path was set, setting |
---|
384 | # are read from a separate config file section otherwise, from the |
---|
385 | # PDP config object |
---|
386 | smClnt = SessionManagerClient( |
---|
387 | uri=sessionManagerURI, |
---|
388 | sslCACertFilePathList=self.sslCACertFilePathList, |
---|
389 | cfg=self.wssecurityCfg) |
---|
390 | except Exception, e: |
---|
391 | log.error("Creating Session Manager client: %s" % e) |
---|
392 | raise InitSessionCtxError() |
---|
393 | |
---|
394 | |
---|
395 | try: |
---|
396 | # Make request for attribute certificate |
---|
397 | return smClnt.getAttCert( |
---|
398 | attributeAuthorityURI=attributeAuthorityURI, |
---|
399 | sessID=sessionId) |
---|
400 | |
---|
401 | except AttributeRequestDenied, e: |
---|
402 | log.error("Request for attribute certificate denied: %s" % e) |
---|
403 | raise PDPUserAccessDenied() |
---|
404 | |
---|
405 | except SessionNotFound, e: |
---|
406 | log.error("No session found: %s" % e) |
---|
407 | raise SessionNotFoundMsg() |
---|
408 | |
---|
409 | except SessionExpired, e: |
---|
410 | log.error("Session expired: %s" % e) |
---|
411 | raise SessionExpiredMsg() |
---|
412 | |
---|
413 | except SessionCertTimeError, e: |
---|
414 | log.error("Session cert. time error: %s" % e) |
---|
415 | raise InvalidSessionMsg() |
---|
416 | |
---|
417 | except InvalidSession, e: |
---|
418 | log.error("Invalid user session: %s" % e) |
---|
419 | raise InvalidSessionMsg() |
---|
420 | |
---|
421 | except Exception, e: |
---|
422 | log.error("Request from Session Manager [%s] to Attribute " |
---|
423 | "Authority [%s] for attribute certificate: %s: %s" % |
---|
424 | (sessionManagerURI, |
---|
425 | attributeAuthorityURI, |
---|
426 | e.__class__, e)) |
---|
427 | raise AttributeCertificateRequestError() |
---|
428 | |
---|
429 | |
---|
430 | def _getAttributeCertificateFromAttributeAuthority(self, |
---|
431 | attributeAuthorityURI, |
---|
432 | username): |
---|
433 | '''Retrieve an Attribute Certificate direct from an Attribute |
---|
434 | Authority. This method is invoked if no session ID or Session |
---|
435 | MAnager endpoint where provided |
---|
436 | |
---|
437 | @type username: basestring |
---|
438 | @param username: user identifier - may be an OpenID URI |
---|
439 | @type attributeAuthorityURI: basestring |
---|
440 | @param attributeAuthorityURI: URI to Attribute Authority service |
---|
441 | @rtype: ndg.security.common.AttCert.AttCert |
---|
442 | @return: Attribute Certificate containing user roles |
---|
443 | ''' |
---|
444 | |
---|
445 | try: |
---|
446 | # Create Attribute Authority client - if a file path was set, |
---|
447 | # settingare read from a separate config file section otherwise, |
---|
448 | # from the PDP config object |
---|
449 | aaClnt = AttributeAuthorityClient( |
---|
450 | uri=attributeAuthorityURI, |
---|
451 | sslCACertFilePathList=self.sslCACertFilePathList, |
---|
452 | cfg=self.wssecurityCfg) |
---|
453 | except Exception, e: |
---|
454 | log.error("Creating Attribute Authority client: %s" % e) |
---|
455 | raise InitSessionCtxError() |
---|
456 | |
---|
457 | |
---|
458 | try: |
---|
459 | # Make request for attribute certificate |
---|
460 | attrCert = aaClnt.getAttCert(userId=username) |
---|
461 | |
---|
462 | |
---|
463 | except AA_AttributeRequestDenied, e: |
---|
464 | log.error("Request for attribute certificate denied: %s" % e) |
---|
465 | raise PDPUserAccessDenied() |
---|
466 | |
---|
467 | # TODO: handle othe specific Exception types here for more fine |
---|
468 | # grained response info |
---|
469 | |
---|
470 | except Exception, e: |
---|
471 | log.error("Request to Attribute Authority [%s] for attribute " |
---|
472 | "certificate: %s: %s", attributeAuthorityURI, |
---|
473 | e.__class__, e) |
---|
474 | raise AttributeCertificateRequestError() |
---|
475 | |
---|
476 | return attrCert |
---|
477 | |
---|
478 | |
---|
479 | |
---|
480 | class PDP(object): |
---|
481 | """Policy Decision Point""" |
---|
482 | |
---|
483 | def __init__(self, policy, pip): |
---|
484 | """Read in a file which determines access policy""" |
---|
485 | self.policy = policy |
---|
486 | self.pip = pip |
---|
487 | |
---|
488 | def evaluate(self, request): |
---|
489 | '''Make access control decision''' |
---|
490 | |
---|
491 | # Look for matching targets to the given resource |
---|
492 | resourceURI = request.resource[Resource.URI_NS] |
---|
493 | matchingTargets = [target for target in self.policy.targets |
---|
494 | if target.regEx.match(resourceURI) is not None] |
---|
495 | |
---|
496 | knownAttributeAuthorityURIs = [] |
---|
497 | for matchingTarget in matchingTargets: |
---|
498 | |
---|
499 | # Make call to the Policy Information Point to pull user |
---|
500 | # attributes applicable to this resource |
---|
501 | if matchingTarget.attributeAuthorityURI not in \ |
---|
502 | knownAttributeAuthorityURIs: |
---|
503 | |
---|
504 | attributeQuery = PIPAttributeQuery() |
---|
505 | attributeQuery[PIPAttributeQuery.SUBJECT_NS] = request.subject |
---|
506 | |
---|
507 | attributeQuery[PIPAttributeQuery.ATTRIBUTEAUTHORITY_NS] = \ |
---|
508 | matchingTarget.attributeAuthorityURI |
---|
509 | |
---|
510 | try: |
---|
511 | attributeResponse = self.pip.attributeQuery(attributeQuery) |
---|
512 | |
---|
513 | except SubjectRetrievalError, e: |
---|
514 | log.exception(e) |
---|
515 | return Response(Response.DECISION_INDETERMINATE, |
---|
516 | message=str(e)) |
---|
517 | |
---|
518 | except Exception, e: |
---|
519 | log.exception(e) |
---|
520 | return Response(Response.DECISION_INDETERMINATE, |
---|
521 | message="An internal error occurred") |
---|
522 | |
---|
523 | knownAttributeAuthorityURIs.append( |
---|
524 | matchingTarget.attributeAuthorityURI) |
---|
525 | |
---|
526 | request.subject[Subject.ROLES_NS] = attributeResponse[ |
---|
527 | Subject.ROLES_NS] |
---|
528 | |
---|
529 | # Match the subject's attributes against the target |
---|
530 | for attr in matchingTarget.attributes: |
---|
531 | if attr in request.subject[Subject.ROLES_NS]: |
---|
532 | return Response(Response.DECISION_PERMIT) |
---|
533 | |
---|
534 | return Response(Response.DECISION_DENY) |
---|
535 | |
---|
536 | |
---|
537 | |
---|