source: TI12-security/trunk/NDG_XACML/ndg/xacml/__init__.py @ 6624

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