source: TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/xacml/__init__.py @ 5397

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/xacml/__init__.py@5397
Revision 5397, 32.0 KB checked in by pjkersha, 11 years ago (diff)

ndg.security.common.authz.msi: added additional logging for PDP and PIP.
ndg.security.common.authz.xacml: added SetFunction? and ConditionSetFunction? implementations to enable support got at-least-one-member of rules.

Line 
1"""XACML Package
2
3NERC DataGrid Project
4
5This package is adapted from the Sun Java XACML implementation ...
6
7Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
8
9Redistribution and use in source and binary forms, with or without
10modification, are permitted provided that the following conditions are met:
11
12  1. Redistribution of source code must retain the above copyright notice,
13     this list of conditions and the following disclaimer.
14
15  2. Redistribution in binary form must reproduce the above copyright
16     notice, this list of conditions and the following disclaimer in the
17     documentation and/or other materials provided with the distribution.
18
19Neither the name of Sun Microsystems, Inc. or the names of contributors may
20be used to endorse or promote products derived from this software without
21specific prior written permission.
22
23This software is provided "AS IS," without a warranty of any kind. ALL
24EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
25ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
26OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
27AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
28AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
29DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
30REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
31INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
32OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
33EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34
35You acknowledge that this software is not designed or intended for use in
36the design, construction, operation or maintenance of any nuclear facility.
37"""
38__author__ = "P J Kershaw"
39__date__ = "13/02/09"
40__copyright__ = "(C) 2009 Science and Technology Facilities Council"
41__contact__ = "Philip.Kershaw@stfc.ac.uk"
42__license__ = "BSD - see LICENSE file in top-level directory"
43__contact__ = "Philip.Kershaw@stfc.ac.uk"
44__revision__ = "$Id$"
45
46import logging
47log = logging.getLogger(__name__)
48
49from elementtree import ElementTree
50from ndg.security.common.utils import getLocalName
51
52from ndg.security.common.authz.xacml.exceptions import ParsingException, \
53    UnknownIdentifierException
54   
55from ndg.security.common.authz.xacml.cond.factory import FunctionFactory, \
56    FunctionTypeException
57
58from ndg.security.common.authz.xacml.attr import AttributeFactory, \
59    AttributeDesignator
60from ndg.security.common.authz.xacml.ctx import Result
61from ndg.security.common.authz.xacml.cond import Apply
62
63class XacmlBase(object):
64    pass
65
66class Subject(XacmlBase):
67    '''XACML Subject designator'''
68    def __init__(self, attributes={}):
69        self.attributes = attributes
70
71class Resource(XacmlBase):
72    '''XACML Resource designator'''
73
74class Action(XacmlBase):
75    '''XACML Action designator'''
76
77class Environment(XacmlBase):
78    '''XACML Environment designator'''
79
80class PolicySet(XacmlBase):
81    def __init__(self):
82          self.policies = []
83          self.combiningAlg = None
84         
85class Policy(XacmlBase):
86
87    def __init__(self,
88                 id='',
89                 ruleCombiningAlg=None,
90                 description='',
91                 target=None,
92                 rules=[],
93                 obligations=[]):
94          self.id = id
95          self.description = description
96          self.rules = rules
97          self.ruleCombiningAlg = ruleCombiningAlg
98          self.obligations = obligations
99          self.target = target
100
101    def encode(self):
102        '''Encode the policy'''
103        raise NotImplemented()
104   
105    @classmethod
106    def getInstance(cls, root=None, source=None):
107        """
108        @type root: ElementTree.Element
109        @param root: ElementTree root element
110        @type source: basestring / file like object
111        @param source: file path or file like object source of data
112        """
113        if root is None:
114            if source is None:
115                raise AttributeError('"root" or "source" keywords must be '
116                                     'provided')
117               
118            elem = ElementTree.parse(source)
119            root = elem.getroot()
120       
121        rules = []
122        for elem in root:
123            localName = getLocalName(elem)
124            if localName == 'Description':
125                description = elem.text.strip()
126               
127            elif localName == 'Target':
128                target = Target.getInstance(elem)
129               
130            elif localName == 'Rule':
131                rules.append(Rule.getInstance(elem))
132           
133        policy = cls(id=root.attrib['PolicyId'], 
134                     ruleCombiningAlg=root.attrib['RuleCombiningAlgId'],
135                     description=description,
136                     target=target,
137                     rules=rules,
138                     obligations=obligations)
139        return policy
140
141class MatchResult(XacmlBase):
142    pass
143
144class Target(XacmlBase):
145    '''The target selects policies relevant to a request'''
146
147    def __init__(self, subjects=None, resources=None, actions=None):
148          self.subjects = subjects
149          self.resources = resources
150          self.actions = actions
151          self.rules = []
152
153    def Match(self, evaluationCtx):
154          return MatchResult()
155       
156    @classmethod
157    def getInstance(cls, root):
158        '''Parse a Target from a given XML ElementTree element
159        '''
160        subjects = None
161        resources = None
162        actions = None
163       
164        for elem in root:
165            localName = getLocalName(elem)
166
167            if localName == "Subjects":
168                subjects = Target._getAttributes(elem, "Subject")
169               
170            elif localName == "Resources":
171                resources = Target._getAttributes(elem, "Resource")
172               
173            elif localName == "Actions":
174                actions = Target._getAttributes(elem, "Action")
175       
176        return cls(subjects=subjects, resources=resources, actions=actions)
177   
178    @staticmethod
179    def _getAttributes(root, prefix):
180        '''Helper method to get Target children elements'''
181        matches = []
182
183        for elem in root:
184            localName = getLocalName(elem)
185
186            if localName == prefix:
187                matches += Target._getMatches(elem, prefix)
188            elif localName == "Any" + prefix:
189                return None
190
191        return matches
192   
193    @staticmethod
194    def _getMatches(root, prefix):
195
196        list = []
197
198        for elem in root:
199            localName = getLocalName(elem)
200
201            if localName == prefix + "Match":
202                list.append(TargetMatch.getInstance(elem, prefix))
203
204        return tuple(list)
205       
206   
207class TargetMatch(XacmlBase):
208    '''Represents the SubjectMatch, ResourceMatch, or ActionMatch XML
209    types in XACML, depending on the value of the type field. This is the
210    part of the Target that actually evaluates whether the specified
211    attribute values in the Target match the corresponding attribute
212    values in the request context.
213    '''
214    types = range(3)
215    SUBJECT, RESOURCE, ACTION = types
216   
217    def __init__(self,
218                 type,
219                 function,
220                 eval,
221                 attributeValue):
222        '''Create a TargetMatch from components.
223         
224        @param type an integer indicating whether this class represents a
225        SubjectMatch, ResourceMatch, or ActionMatch
226        @param function the Function that represents the MatchId
227        @param eval the AttributeDesignator or AttributeSelector to be used to
228        select attributes from the request context
229        @param attrValue the AttributeValue to compare against
230        @raise TypeError if the input type isn't a valid value
231        '''
232        if type not in self.__class__.types:
233            raise TypeError("Type is [%d] but it must be one of %r" % 
234                            (type, self.__class__.types))
235        self.type = type
236        self.function = function
237        self.eval = eval
238        self.attrValue = attributeValue
239
240    def _getType(self):
241        return getattr(self, '_type', None)
242   
243    def _setType(self, type):
244        if type not in self.__class__.types:
245            raise TypeError('Type value "%d" not recognised, expecting one of '
246                            '%r types' % (type, self.__class__.types))
247        self._type = type
248       
249    type = property(fget=_getType, fset=_setType, 
250                    doc="the type of match for this target")
251   
252    @classmethod
253    def getInstance(cls, root, prefix):
254        '''Creates a TargetMatch by parsing a node, using the
255        input prefix to determine whether this is a SubjectMatch,
256        ResourceMatch, or ActionMatch.
257     
258        @param root the node to parse for the TargetMatch
259        @param prefix a String indicating what type of TargetMatch
260        to instantiate (Subject, Resource, or Action)
261        @param xpathVersion the XPath version to use in any selectors, or
262        null if this is unspecified (ie, not supplied in
263        the defaults section of the policy)
264
265        @return a new TargetMatch constructed by parsing
266        '''
267
268        type = ["Subject", "Resource", "Action"].index(prefix)
269        if type not in cls.types:
270            raise TypeError("Unknown TargetMatch type: %s" % prefix)
271
272        # function type
273        funcId = root.attrib["MatchId"]
274        factory = FunctionFactory.getTargetInstance()
275        try:
276            function = factory.createFunction(funcId)
277        except UnknownIdentifierException, e:
278            raise ParsingException("Unknown MatchId: %s" % e)
279       
280        except FunctionTypeException, e:
281            # try to create an abstract function
282            try:
283                function = factory.createAbstractFunction(funcId, root)
284            except Exception, e:
285                raise ParsingException("invalid abstract function: %s" % e)
286           
287        attributeFactory = AttributeFactory.getInstance()
288       
289        # Get the designator or selector being used, and the attribute
290        # value paired with it
291        for elem in root:
292            localName = getLocalName(elem)
293
294            if localName == prefix + "AttributeDesignator":
295                eval = AttributeDesignator.getInstance(elem, type)
296               
297            elif localName == "AttributeSelector":
298                eval = AttributeSelector.getInstance(elem)
299               
300            elif localName == "AttributeValue":
301                try:
302                    attributeValue = attributeFactory.createValue(root=elem)
303                except UnknownIdentifierException, e:
304                    raise ParsingException("Unknown Attribute Type: %s" % e)
305
306        # finally, check that the inputs are valid for this function
307        inputs = [attributeValue, eval]
308        function.checkInputsNoBag(inputs)
309       
310        return cls(type, function, eval, attributeValue)
311   
312
313    def match(self, context):
314        '''determines whether this TargetMatch matches
315        the input request (whether it is applicable)
316
317        @param context the representation of the request
318
319        @return the result of trying to match the TargetMatch and the request
320        '''
321       
322        result = eval.evaluate(context)
323       
324        if result.indeterminate():
325            # in this case, we don't ask the function for anything, and we
326            # simply return INDETERMINATE
327            return MatchResult(MatchResult.INDETERMINATE, result.getStatus())
328       
329
330        bag = result.getAttributeValue()
331
332        if not bag.isEmpty():
333           
334            # we got back a set of attributes, so we need to iterate through
335            # them, seeing if at least one matches
336            it = bag.iterator()
337            atLeastOneError = False
338            firstIndeterminateStatus = None
339
340            while it.hasNext():
341                inputs = []
342
343                inputs.add(attrValue)
344                inputs.add(it.next())
345
346                # do the evaluation
347                match = evaluateMatch(inputs, context)
348               
349                # we only need one match for this whole thing to match
350                if match.getResult() == MatchResult.MATCH:
351                    return match
352
353                # if it was INDETERMINATE, we want to remember for later
354                if match.getResult() == MatchResult.INDETERMINATE:
355                    atLeastOneError = True
356
357                    # there are no rules about exactly what status data
358                    # should be returned here, so like in the combining
359                    # also, we'll just track the first error
360                    if firstIndeterminateStatus == None:
361                        firstIndeterminateStatus = match.getStatus()
362
363            # if we got here, then nothing matched, so we'll either return
364            # INDETERMINATE or NO_MATCH
365            if atLeastOneError:
366                return MatchResult(MatchResult.INDETERMINATE,
367                                       firstIndeterminateStatus)
368            else:
369                return MatchResult(MatchResult.NO_MATCH)
370
371        else:
372            # this is just an optimization, since the loop above will
373            # actually handle this case, but this is just a little
374            # quicker way to handle an empty bag
375            return MatchResult(MatchResult.NO_MATCH)
376   
377    def evaluateMatch(self, inputs, context):
378        '''Private helper that evaluates an individual match'''
379       
380        # evaluate the function
381        result = function.evaluate(inputs, context)
382
383        # if it was indeterminate, then that's what we return immediately
384        if result.indeterminate():
385            return MatchResult(MatchResult.INDETERMINATE,
386                               result.getStatus())
387
388        # otherwise, we figure out if it was a match
389        bool = result.getAttributeValue()
390
391        if bool.getValue():
392            return MatchResult(MatchResult.MATCH)
393        else:
394            return MatchResult(MatchResult.NO_MATCH)
395
396    def encode(self, output, indenter=None):
397        '''Encodes this TargetMatch into its XML representation
398        and writes this encoding to the given OutputStream with no
399        indentation.
400        @param output a stream into which the XML-encoded data is written'''
401        raise NotImplementedError()
402   
403   
404class Status(XacmlBase):
405    STATUS_MISSING_ATTRIBUTE = \
406          "urn:oasis:names:tc:xacml:1.0:status:missing-attribute"
407    STATUS_OK = "urn:oasis:names:tc:xacml:1.0:status:ok"
408    STATUS_PROCESSING_ERROR = \
409          "urn:oasis:names:tc:xacml:1.0:status:processing-error"
410    STATUS_SYNTAX_ERROR = \
411          "urn:oasis:names:tc:xacml:1.0:status:syntax-error"       
412
413class Effect(XacmlBase):
414    def __str__(self):
415        raise NotImplementedError()
416
417             
418class DenyEffect(Effect):
419    def __str__(self):
420        return 'deny'
421         
422class PermitEffect(Effect):
423    def __str__(self):
424        return 'permit'
425
426class PolicyTreeElement(XacmlBase):
427    pass
428
429class Rule(PolicyTreeElement):
430    '''Represents the RuleType XACML type. This has a target for matching, and
431    encapsulates the condition and all sub-operations that make up the heart
432    of most policies.
433    '''
434    def __init__(self, ruleId, effect, description, target, condition):
435        '''Creates a new <code>Rule</code> object.
436       
437        @param ruleId: the rule's identifier
438        @param effect: the effect to return if the rule applies (either
439                      Permit or Deny) as specified in <code>Result</code>
440        @param description: a textual description, or None
441        @param target: the rule's target, or None if the target is to be
442                      inherited from the encompassing policy
443        @param condition: the rule's condition, or None if there is none
444        '''
445       
446        self.idAttr = ruleId
447       
448        # Effect is the intended consequence of the satisfied rule. It can
449        # either take the value Permit or Deny.
450        self.effect = effect
451       
452        self.description = description
453       
454        # Target, as in the case of a policy, helps in determining whether or
455        # not a rule is relevant for a request. The mechanism for achieving
456        # this is also similar to how it is done in the case of a target for a
457        # policy.
458        self.target = target
459       
460        # Conditions are statements about attributes that upon evaluation
461        # return either True, False, or Indeterminate.
462        self.condition = condition
463       
464    @classmethod
465    def getInstance(cls, root):
466        '''Returns a new instance of the Rule class based on an XML element.
467        The element must be the root of an XML RuleType.
468       
469        @param root: the root of a RuleType XML type
470        @raise ParsingException: if the RuleType is invalid
471        '''
472        id = None
473        name = None
474        effect = 0
475        description = None
476        target = None
477        condition = None
478
479        id = root.attrib.get("RuleId")
480        if id is None:
481            raise ParsingException("Error parsing required attribute RuleId")
482       
483        str = root.attrib.get("Effect")
484        if str == "Permit":
485            effect = Result.DECISION_PERMIT
486        elif str == "Deny":
487            effect = Result.DECISION_DENY
488        else:
489            raise ParsingException("Invalid Effect: %s" % effect)
490       
491
492        # next, get the elements
493        for elem in list(root):
494            cname = getLocalName(elem)
495
496            if cname == "Description":
497                description = elem.text
498               
499            elif cname == "Target":
500                target = Target.getInstance(elem)
501               
502            elif cname == "Condition":
503                condition = Apply.getConditionInstance(elem)
504           
505        return Rule(id, effect, description, target, condition)
506   
507    def getEffect(self): 
508        '''Returns the effect that this <code>Rule</code> will return from
509        the evaluate method (Permit or Deny) if the request applies.
510       
511        @return a decision effect, as defined in <code>Result</code>
512        '''
513        return self.effect
514   
515    def getId(self):
516        '''Returns the id of this <code>Rule</code>
517       
518        @return the rule id'''
519        return self.idAttr
520   
521    def getDescription(self):
522        '''Returns the given description of this <code>Rule</code> or None if
523        there is no description
524       
525        @return: the description or None'''
526        return self.description
527     
528    def getTarget(self):
529        '''Returns the target for this Rule or None if there is no target
530       
531        @return: the rule's target'''
532        return self.target
533
534   
535    def getChildren(self):
536        '''Since a rule is always a leaf in a policy tree because it can have
537        no children, this always returns an empty list.
538       
539        @return: a list with no elements'''
540        return []
541   
542    def getCondition(self):
543        '''Returns the condition for this <code>Rule</code> or None if there
544        is no condition
545       
546        @return: the rule's condition
547        '''
548        return self.condition
549   
550    def match(self, context):
551        '''Given the input context sees whether or not the request matches this
552        <code>Rule</code>'s <code>Target</code>. Note that unlike the matching
553        done by the <code>evaluate</code> method, if the <code>Target</code>
554        is missing than this will return Indeterminate. This lets you write
555        your own custom matching routines for rules but lets evaluation
556        proceed normally.
557       
558        @param context the representation of the request
559       
560        @return the result of trying to match this rule and the request
561        '''
562        if target is None: 
563            code = []
564            code.append(Status.STATUS_PROCESSING_ERROR)
565            status = Status(code, "no target available for matching a rule")
566
567            return MatchResult(MatchResult.INDETERMINATE, status)
568       
569
570        return target.match(context)
571   
572    def evaluate(self, context): 
573        '''Evaluates the rule against the supplied context. This will check
574        that  the target matches, and then try to evaluate the condition. If
575        the target and condition apply, then the rule's effect is returned in
576        the result.
577
578        Note that rules are not required to have targets. If no target is
579        specified, then the rule inherits its parent's target. In the event
580        that this Rule has no Target then the match is assumed to be true,
581        since evaluating a policy tree to this level required the parent's
582        target to match.
583       
584        @param context: the representation of the request we're evaluating
585       
586        @return: the result of the evaluation
587        '''
588        # If the Target is None then it's supposed to inherit from the
589        # parent policy, so we skip the matching step assuming we wouldn't
590        # be here unless the parent matched
591        if target is not None: 
592            match = target.match(context)
593            result = match.getResult()
594
595            # if the target didn't match, then this Rule doesn't apply
596            if result == MatchResult.NO_MATCH:
597                return Result(Result.DECISION_NOT_APPLICABLE,
598                              context.getResourceId().encode())
599
600            # if the target was indeterminate, we can't go on
601            if result == MatchResult.INDETERMINATE:
602                return Result(Result.DECISION_INDETERMINATE,
603                              match.getStatus(),
604                              context.getResourceId().encode())
605       
606
607        # if there's no condition, then we just return the effect...
608        if condition is None:
609            return Result(effectAttr, context.getResourceId().encode())
610
611        # ...otherwise we evaluate the condition
612        result = condition.evaluate(context)
613       
614        if result.indeterminate():
615            # if it was INDETERMINATE, then that's what we return
616            return Result(Result.DECISION_INDETERMINATE,
617                          result.getStatus(),
618                          context.getResourceId().encode())
619        else: 
620            # otherwise we return the effect on true, and NA on false
621            boolVal = result.getAttributeValue()
622
623            if boolVal.getValue():
624                return Result(effectAttr,
625                              context.getResourceId().encode())
626            else:
627                return Result(Result.DECISION_NOT_APPLICABLE,
628                              context.getResourceId().encode())
629   
630    def encode(self, output=None, indenter=None): 
631        '''Encodes this Rule into its XML representation and writes
632        this encoding to the given <code>OutputStream</code> with
633        indentation.
634       
635        @param output: a stream into which the XML-encoded data is written
636        @param indenter: an object that creates indentation strings'''
637        raise NotImplementedError()
638   
639
640
641         
642class Attribute(XacmlBase):
643    def __init__(self, id, type=None, issuer=None, issueInstant=None, 
644                 value=None):
645        self.id = id
646        self.type = type or value.__class__
647        self.issuer = issuer
648        self.issueInstant = issueInstant
649        self.value = value
650
651       
652class Request(XacmlBase):
653    '''XACML Request XacmlBase
654   
655    TODO: refactor from this initial placeholder'''
656    def __init__(self, subject, resource, action=None, environment={}):
657          self.subject = subject
658          self.resource = resource
659          self.action = action
660          self.environment = environment
661
662class Response(XacmlBase):
663    pass
664
665
666class PDP(XacmlBase):
667    '''Modify PDPInterface to use the four XACML request designators: subject,
668    resource, action and environment
669   
670    This is an initial iteration toward a complete XACML implementation'''
671    def __init__(self, *arg, **kw):
672          pass
673   
674    def evaluate(self, request):
675          '''Make access control decision - override this in a derived class to
676          implement the decision logic but this method may be called within
677          the derived method to check input types
678         
679          @param request: request object containing the subject, resource,
680          action and environment
681          @type request: ndg.security.common.authz.xacml.Request
682          @return reponse object
683          @rtype: ndg.security.common.authz.xacml.Response
684          '''
685          raise NotImplementedError()
686
687
688class RuleCombiningAlg(XacmlBase):
689    id = None
690
691class DenyOverrides(RuleCombiningAlg):
692   '''Deny-overrides: If any rule evaluates to Deny, then the final
693   authorization decision is also Deny.'''
694   id = 'Deny-overrides'
695   
696class OrderedDenyOverrides(RuleCombiningAlg):
697    '''Ordered-deny-overrides: Same as deny-overrides, except the order in
698    which relevant rules are evaluated is the same as the order in which they
699    are added in the policy.'''
700    id = 'Ordered-deny-overrides'
701   
702class PermitOverrides(RuleCombiningAlg):
703    '''Permit-overrides: If any rule evaluates to Permit, then the final
704    authorization decision is also Permit.'''
705   
706class OrderedPermitOverrides(RuleCombiningAlg):
707    '''Ordered-permit-overrides: Same as permit-overrides, except the order in
708    which relevant rules are evaluated is the same as the order in which they
709    are added in the policy.'''
710    id = 'Ordered-permit-overrides'
711   
712class FirstApplicable(RuleCombiningAlg):
713    '''First-applicable: The result of the first relevant rule encountered is
714    the final authorization decision as well.'''
715    id = 'First-applicable'
716
717
718class EvaluationCtx(object):
719
720    # The standard URI for listing a resource's id
721    RESOURCE_ID ="urn:oasis:names:tc:xacml:1.0:resource:resource-id"
722
723    # The standard URI for listing a resource's scope
724    RESOURCE_SCOPE = "urn:oasis:names:tc:xacml:1.0:resource:scope"
725
726    # Resource scope of Immediate (only the given resource)
727    SCOPE_IMMEDIATE = 0
728
729    # Resource scope of Children (the given resource and its direct
730    # children)
731    SCOPE_CHILDREN = 1
732
733    # Resource scope of Descendants (the given resource and all descendants
734    # at any depth or distance)
735    SCOPE_DESCENDANTS = 2
736   
737    def getRequestRoot(self):
738        '''Returns the DOM root of the original RequestType XML document, if
739        this context is backed by an XACML Request. If this context is not
740        backed by an XML representation, then an exception is thrown.'''
741        raise NotImplementedError()
742
743    def getResourceId(self):
744        '''Returns the identifier for the resource being requested.'''
745        raise NotImplementedError()
746
747    def getScope(self):
748        '''Returns the resource scope, which will be one of the three fields
749        denoting Immediate, Children, or Descendants.'''
750        raise NotImplementedError()
751
752    def setResourceId(self, resourceId):
753        '''Changes the value of the resource-id attribute in this context. This
754        is useful when you have multiple resources (ie, a scope other than
755        IMMEDIATE), and you need to keep changing only the resource-id to
756        evaluate the different effective requests.'''
757        raise NotImplementedError()
758
759    def getCurrentTime(self):
760        '''Returns the cached value for the current time. If the value has
761        never been set by a call to setCurrentTime, or if caching
762        is not enabled in this instance, then this will return null.'''
763        raise NotImplementedError()
764
765    def setCurrentTime(self, currentTime):
766        '''Sets the current time for this evaluation. If caching is not enabled
767        for this instance then the value is ignored.
768     
769        @param currentTime the dynamically resolved current time'''
770        raise NotImplementedError()
771
772    def getCurrentDate(self):
773        '''Returns the cached value for the current date. If the value has
774        never been set by a call to setCurrentDate, or if caching
775        is not enabled in this instance, then this will return null.'''
776        raise NotImplementedError()
777
778    def setCurrentDate(self, currentDate):
779        '''Sets the current date for this evaluation. If caching is not enabled
780        for this instance then the value is ignored.'''
781        raise NotImplementedError()
782
783    def getCurrentDateTime(self):
784        '''Returns the cached value for the current dateTime. If the value has
785        never been set by a call to setCurrentDateTime, or if
786        caching is not enabled in this instance, then this will return null.
787        '''
788        raise NotImplementedError()
789
790    def setCurrentDateTime(self, currentDateTime):
791        '''Sets the current dateTime for this evaluation. If caching is not
792        enabled for this instance then the value is ignored.
793     
794        @param currentDateTime the dynamically resolved current dateTime'''
795        raise NotImplementedError()
796
797    def getSubjectAttribute(self, type, id, category):
798        '''Returns available subject attribute value(s) ignoring the issuer.
799     
800        @param type the type of the attribute value(s) to find
801        @param id the id of the attribute value(s) to find
802        @param category the category the attribute value(s) must be in
803     
804        @return a result containing a bag either empty because no values were
805        found or containing at least one value, or status associated with an
806        Indeterminate result'''
807        raise NotImplementedError()
808
809    def getSubjectAttribute(self, type, id, issuer, category):
810        '''Returns available subject attribute value(s).
811     
812        @param type the type of the attribute value(s) to find
813        @param id the id of the attribute value(s) to find
814        @param issuer the issuer of the attribute value(s) to find or null
815        @param category the category the attribute value(s) must be in
816     
817        @return a result containing a bag either empty because no values were
818        found or containing at least one value, or status associated with an
819        Indeterminate result'''
820        raise NotImplementedError()
821   
822    def getResourceAttribute(self, type, id, issuer):
823        '''Returns available resource attribute value(s).
824     
825        @param type the type of the attribute value(s) to find
826        @param id the id of the attribute value(s) to find
827        @param issuer the issuer of the attribute value(s) to find or null
828     
829        @return a result containing a bag either empty because no values were
830        found or containing at least one value, or status associated with an
831        Indeterminate result'''
832        raise NotImplementedError()
833
834    def getActionAttribute(self, type, id, issuer):
835        '''Returns available action attribute value(s).
836     
837        @param type the type of the attribute value(s) to find
838        @param id the id of the attribute value(s) to find
839        @param issuer the issuer of the attribute value(s) to find or null
840     
841        @return a result containing a bag either empty because no values were
842        found or containing at least one value, or status associated with an
843        Indeterminate result'''
844        raise NotImplementedError()
845
846    def getEnvironmentAttribute(self, type, id, issuer):
847        '''Returns available environment attribute value(s).
848     
849        @param type the type of the attribute value(s) to find
850        @param id the id of the attribute value(s) to find
851        @param issuer the issuer of the attribute value(s) to find or null
852     
853        @return a result containing a bag either empty because no values were
854        found or containing at least one value, or status associated with an
855        Indeterminate result'''
856        raise NotImplementedError()
857
858    def getAttribute(self, contextPath, namespaceNode, type, xpathVersion):
859        '''Returns the attribute value(s) retrieved using the given XPath
860        expression.
861     
862        @param contextPath the XPath expression to search
863        @param namespaceNode the DOM node defining namespace mappings to use,
864                            or null if mappings come from the context root
865        @param type the type of the attribute value(s) to find
866        @param xpathVersion the version of XPath to use
867     
868        @return a result containing a bag either empty because no values were
869       
870        found or containing at least one value, or status associated with an
871        Indeterminate result'''
872        raise NotImplementedError()
Note: See TracBrowser for help on using the repository browser.