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

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

Completed functionality for policy target creation

Line 
1"""XACML Policy Decision Point module
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "13/02/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
13import logging
14log = logging.getLogger(__name__)
15
16from ndg.security.common.authz.pdp import PDPInterface
17
18class XacmlBase(object):
19    pass
20
21class Subject(XacmlBase):
22    '''XACML Subject designator'''
23
24class Resource(XacmlBase):
25    '''XACML Resource designator'''
26
27class Action(XacmlBase):
28    '''XACML Action designator'''
29
30class Environment(XacmlBase):
31    '''XACML Environment designator'''
32
33class PolicySet(XacmlBase):
34    def __init__(self):
35          self.policies = []
36          self.combiningAlg = None
37         
38class Policy(XacmlBase):
39
40    def __init__(self,
41                     id,
42                     combiningAlg,
43                     description,
44                     target,
45                     ruleList):
46          self.id = id
47          self.description = description
48          self.ruleList = ruleList
49          self.combiningAlg = combiningAlg
50          self.obligations = []
51          self.target = target
52
53    def encode(self):
54        '''Encode the policy'''
55        raise NotImplemented()
56
57class MatchResult(XacmlBase):
58    pass
59
60class Target(XacmlBase):
61    '''The target selects policies relevant to a request'''
62
63    def __init__(self, subjects=[], resources=[], actions=[]):
64          self.subjects = subjects
65          self.resources = resources
66          self.actions = actions
67          self.rules = []
68
69    def Match(self, evaluationCtx):
70          return MatchResult()
71   
72   
73class AttributeDesignator(XacmlBase):
74    ACTION_TARGET, ENVIRONMENT_TARGET, RESOURCE_TARGET, SUBJECT_TARGET=range(4)
75
76    def __init__(self, target, type, id, mustBePresent=False, issuer=None):
77          self.target = target
78          self.type = type
79          self.id = id
80          self.mustBePresent = mustBePresent
81          self.issuer = issuer
82
83
84class TargetMatch(XacmlBase):
85    '''Represents the SubjectMatch, ResourceMatch, or ActionMatch XML
86    types in XACML, depending on the value of the type field. This is the
87    part of the Target that actually evaluates whether the specified
88    attribute values in the Target match the corresponding attribute
89    values in the request context.
90    '''
91    types = range(3)
92    SUBJECT, RESOURCE, ACTION = types
93   
94    def __init__(self,
95                 type,
96                 function,
97                 eval,
98                 attributeValue):
99        '''Create a TargetMatch from components.
100         
101        @param type an integer indicating whether this class represents a
102        SubjectMatch, ResourceMatch, or ActionMatch
103        @param function the Function that represents the MatchId
104        @param eval the AttributeDesignator or AttributeSelector to be used to
105        select attributes from the request context
106        @param attrValue the AttributeValue to compare against
107        @raise TypeError if the input type isn't a valid value
108        '''
109        self.type = type
110        self.function = function
111        self.eval = eval
112        self.attrValue = attributeValue
113
114    def _getType(self):
115        return getattr(self, '_type', None)
116   
117    def _setType(self, type):
118        if type not in self.__class__.types:
119            raise TypeError('Type value "%d" not recognised, expecting one of '
120                            '%r types' % (type, self.__class__.types))
121        self._type = type
122       
123    type = property(fget=_getType, fset=_setType, 
124                    doc="the type of match for this target")
125   
126    def getInstance(self, root, prefix, xpathVersion):
127        '''Creates a TargetMatch by parsing a node, using the
128        input prefix to determine whether this is a SubjectMatch,
129        ResourceMatch, or ActionMatch.
130     
131        @param root the node to parse for the TargetMatch
132        @param prefix a String indicating what type of TargetMatch
133        to instantiate (Subject, Resource, or Action)
134        @param xpathVersion the XPath version to use in any selectors, or
135        null if this is unspecified (ie, not supplied in
136        the defaults section of the policy)
137
138        @return a new TargetMatch constructed by parsing
139        '''
140        raise NotImplementedError()
141
142    def match(self, context):
143        '''determines whether this <code>TargetMatch</code> matches
144        the input request (whether it is applicable)
145
146        @param context the representation of the request
147
148        @return the result of trying to match the TargetMatch and the request
149        '''
150       
151        result = eval.evaluate(context)
152       
153        if result.indeterminate():
154            # in this case, we don't ask the function for anything, and we
155            # simply return INDETERMINATE
156            return MatchResult(MatchResult.INDETERMINATE, result.getStatus())
157       
158
159        bag = result.getAttributeValue()
160
161        if not bag.isEmpty():
162           
163            # we got back a set of attributes, so we need to iterate through
164            # them, seeing if at least one matches
165            it = bag.iterator()
166            atLeastOneError = False
167            firstIndeterminateStatus = None
168
169            while it.hasNext():
170                inputs = []
171
172                inputs.add(attrValue)
173                inputs.add(it.next())
174
175                # do the evaluation
176                match = evaluateMatch(inputs, context)
177               
178                # we only need one match for this whole thing to match
179                if match.getResult() == MatchResult.MATCH:
180                    return match
181
182                # if it was INDETERMINATE, we want to remember for later
183                if match.getResult() == MatchResult.INDETERMINATE:
184                    atLeastOneError = True
185
186                    # there are no rules about exactly what status data
187                    # should be returned here, so like in the combining
188                    # also, we'll just track the first error
189                    if firstIndeterminateStatus == None:
190                        firstIndeterminateStatus = match.getStatus()
191
192            # if we got here, then nothing matched, so we'll either return
193            # INDETERMINATE or NO_MATCH
194            if atLeastOneError:
195                return MatchResult(MatchResult.INDETERMINATE,
196                                       firstIndeterminateStatus)
197            else:
198                return MatchResult(MatchResult.NO_MATCH)
199
200        else:
201            # this is just an optimization, since the loop above will
202            # actually handle this case, but this is just a little
203            # quicker way to handle an empty bag
204            return MatchResult(MatchResult.NO_MATCH)
205   
206    def evaluateMatch(self, inputs, context):
207        '''Private helper that evaluates an individual match'''
208       
209        # evaluate the function
210        result = function.evaluate(inputs, context)
211
212        # if it was indeterminate, then that's what we return immediately
213        if result.indeterminate():
214            return MatchResult(MatchResult.INDETERMINATE,
215                               result.getStatus())
216
217        # otherwise, we figure out if it was a match
218        bool = result.getAttributeValue()
219
220        if bool.getValue():
221            return MatchResult(MatchResult.MATCH)
222        else:
223            return MatchResult(MatchResult.NO_MATCH)
224
225    def encode(self, output, indenter=None):
226        '''Encodes this TargetMatch</code> into its XML representation
227        and writes this encoding to the given <code>OutputStream</code> with no
228        indentation.
229        @param output a stream into which the XML-encoded data is written'''
230        raise NotImplementedError()
231   
232   
233class FunctionBase(XacmlBase):
234    FUNCTION_NS = "urn:oasis:names:tc:xacml:1.0:function:"
235   
236    def __init__(self, 
237                 functionName, 
238                 functionId=None, 
239                 paramType=None,
240                 paramIsBag=False,
241                 numParams=0, 
242                 minParams=0,
243                 returnType='', 
244                 returnsBag=False):
245         
246        self.functionName = functionName
247        self.functionId = functionId
248        self.returnType = None
249        self.returnsBag = False
250   
251        self.singleType = True;
252   
253        self.paramType = paramType
254        self.paramIsBag = paramIsBag
255        self.numParams = numParams
256        self.minParams = minParams
257       
258 
259    def _setFunctionName(self, functionName):
260          if functionName not in self.__class__.supportedIdentifiers:
261              functionList = ', '.join(self.__class__.supportedIdentifiers)
262              raise TypeError("Function name [%s] is not on of the recognised "
263                              "types: %s" % (functionName, functionList))
264          self._functionName = functionName
265         
266    def _getFunctionName(self):
267          return getattr(self, '_functionName', None)
268   
269    functionName = property(fset=_setFunctionName,
270                                    fget=_getFunctionName)
271         
272    def checkInputs(self, inputs):
273        '''Checks that the given inputs are of the right types, in the right
274        order, and are the right number for this function to evaluate.'''
275        raise NotImplementedError()
276           
277    def checkInputsNoBag(self, inputs):
278        '''Checks that the given inputs are of the right types, in the right
279        order, and are the right number for this function to evaluate.'''
280        raise NotImplementedError()
281 
282    def evaluate(self, inputs, context):
283        '''Evaluates the Function using the given inputs.'''
284        raise NotImplementedError()
285     
286    def evalArgs(self, params, context, args):
287        '''Evaluates each of the parameters, in order, filling in the argument
288        array with the resulting values. If any error occurs, this method
289        returns the error, otherwise null is returned, signalling that
290        evaluation was successful for all inputs, and the resulting argument
291        list can be used.
292       
293        @param params a list of Evaluatable objects representing the parameters
294        to evaluate
295        @param context the representation of the request
296        @param args an array as long as the params list that will, on return,
297        contain the AttributeValues generated from evaluating all parameters
298
299        @return None if no errors were encountered, otherwise
300        an EvaluationResult representing the error
301        '''
302        it = params.iterator()
303        index = 0
304
305        while it.hasNext():
306            # get and evaluate the next parameter
307            eval = it.next()
308            result = eval.evaluate(context)
309
310            # If there was an error, pass it back...
311            if result.indeterminate():
312                return result
313
314            # ...otherwise save it and keep going
315            args[index] = result.getAttributeValue()
316            index += 1
317           
318        return None
319   
320
321class MatchFunction(FunctionBase):
322    NAME_REGEXP_STRING_MATCH = \
323          "urn:oasis:names:tc:xacml:1.0:function:regexp-string-match"
324    NAME_RFC822NAME_MATCH = \
325          "urn:oasis:names:tc:xacml:1.0:function:rfc822Name-match"
326    NAME_X500NAME_MATCH = \
327          "urn:oasis:names:tc:xacml:1.0:function:x500Name-match"     
328
329    supportedIdentifiers = (NAME_REGEXP_STRING_MATCH, 
330                            NAME_RFC822NAME_MATCH,
331                            NAME_X500NAME_MATCH)
332   
333    lut = {
334          NAME_REGEXP_STRING_MATCH: 'regexpStringMatch',
335          NAME_RFC822NAME_MATCH:    'rfc822NameMatch',
336          NAME_X500NAME_MATCH:      'x500NameMatch'
337    }
338   
339    def __init__(self, functionName, **kw):
340          super(MatchFunction, self).__init__(functionName, **kw)
341
342    def regexpStringMatch(self, regex, val):
343          return re.match(regex, val) is not None
344   
345    def rfc822NameMatch(self, *inputs):
346        raise NotImplementedError()
347   
348    def x500NameMatch(self, *inputs):
349        raise NotImplementedError()
350   
351    def evaluate(self, inputs, context):
352          matchFunction = getattr(self, MatchFunction.lut[self.functionName])
353          match = matchFunction(self, *inputs)
354          if match:
355                return EvaluationResult(status=Status.STATUS_OK)
356
357
358class EqualFunction(FunctionBase):
359    supportedIdentifiers = (
360          "urn:oasis:names:tc:xacml:1.0:function:anyURI-equal",
361          "urn:oasis:names:tc:xacml:1.0:function:base64Binary-equal",
362          "urn:oasis:names:tc:xacml:1.0:function:boolean-equal",
363          "urn:oasis:names:tc:xacml:1.0:function:date-equal",
364          "urn:oasis:names:tc:xacml:1.0:function:dateTime-equal",
365          "urn:oasis:names:tc:xacml:1.0:function:dayTimeDuration-equal",
366          "urn:oasis:names:tc:xacml:1.0:function:double-equal",
367          "urn:oasis:names:tc:xacml:1.0:function:hexBinary-equal",
368          "urn:oasis:names:tc:xacml:1.0:function:integer-equal",
369          "urn:oasis:names:tc:xacml:1.0:function:rfc822Name-equal",
370          "urn:oasis:names:tc:xacml:1.0:function:string-equal",
371          "urn:oasis:names:tc:xacml:1.0:function:time-equal",
372          "urn:oasis:names:tc:xacml:1.0:function:x500Name-equal",
373          "urn:oasis:names:tc:xacml:1.0:function:yearMonthDuration-equal"
374    )
375
376    (NAME_ANYURI_EQUAL,
377    NAME_BASE64BINARY_EQUAL,
378    NAME_BOOLEAN_EQUAL,
379    NAME_DATE_EQUAL,
380    NAME_DATETIME_EQUAL,
381    NAME_DAYTIME_DURATION_EQUAL,
382    NAME_DOUBLE_EQUAL,
383    NAME_HEXBINARY_EQUAL,
384    NAME_INTEGER_EQUAL,
385    NAME_RFC822NAME_EQUAL,
386    NAME_STRING_EQUAL,
387    NAME_TIME_EQUAL,
388    NAME_X500NAME_EQUAL,
389    NAME_YEARMONTH_DURATION_EQUAL) = supportedIdentifiers
390
391    lut = {
392          NAME_STRING_EQUAL: 'stringEqual'
393    }
394   
395    typeMap = {NAME_STRING_EQUAL: basestring}
396   
397    def __init__(self, functionName, **kw):
398          super(EqualFunction, self).__init__(functionName, **kw)
399
400    def evaluate(self, inputs, evaluationCtx):
401        function = EqualFunction.lut.get(self.functionName)
402        if function is None:
403            if self.functionName in supportedIdentifiers:
404                raise NotImplementedError("No implementation is available for "
405                                          "%s" % self.functionName)           
406            else:
407                raise AttributeError('function name "%s" not recognised '
408                                     'for %s' % (self.functionName,
409                                                 self.__class__.__name__))
410                                 
411        return getattr(self, function)(inputs, evaluationCtx)
412   
413    def stringEqual(self, inputs, evaluationCtx):
414        result = self.evalArgs(inputs, context, argValues)
415        if result is not None:
416            return result
417         
418        return EvaluationResult(argValues[0] == argValues[1])
419   
420    def getArgumentType(functionName):
421        datatype = EqualFunction.typeMap.get(functionName);
422        if datatype is None:
423            raise AttributeError("Not a standard function: %s" % functionName)
424         
425        return datatype
426   
427   
428class Status(XacmlBase):
429    STATUS_MISSING_ATTRIBUTE = \
430          "urn:oasis:names:tc:xacml:1.0:status:missing-attribute"
431    STATUS_OK = "urn:oasis:names:tc:xacml:1.0:status:ok"
432    STATUS_PROCESSING_ERROR = \
433          "urn:oasis:names:tc:xacml:1.0:status:processing-error"
434    STATUS_SYNTAX_ERROR = \
435          "urn:oasis:names:tc:xacml:1.0:status:syntax-error" 
436     
437class EvaluationResult(XacmlBase):
438    def __init__(self, 
439                 attributeValue=None, 
440                 status=None, 
441                 indeterminate=False):
442        self.status = status
443        self.attributeValue = attributeValue
444        self.indeterminate = indeterminate
445
446
447class Evaluatable(XacmlBase):
448    '''Generic interface that is implemented by all objects that can appear in
449    an ApplyType. This lets the evaluation code of Apply and
450    functions iterate through their members and evaluate them, working only
451    on the returned values or errors.'''
452   
453    def evaluate(self, context):
454        '''Evaluates the object using the given context, and either returns an
455        error or a resulting value.
456   
457        @param context the representation of the request
458        @return the result of evaluation'''
459        raise NotImplementedError()
460
461    def getType(self):
462        '''Get the type of this object.  This may be the data type of an
463        Attribute or the return type of an
464        AttributeDesignator, etc.
465   
466        @return the type of data represented by this object'''
467        raise NotImplementedError()
468
469    def evaluatesToBag(self):
470        '''Tells whether evaluation will return a bag or a single value.
471   
472        @return true if evaluation will return a bag, false otherwise'''
473        raise NotImplementedError()
474
475    def getChildren(self):
476        '''Returns all children, in order, of this element in the Condition
477        tree, or en empty set if this element has no children. In XACML 1.x,
478        only the ApplyType ever has children.
479   
480        @return a list of Evaluatables'''
481        raise NotImplementedError()
482
483    def encode(self, output, indenter=None):
484        '''Encodes this Evaluatable into its XML representation and
485        writes this encoding to the given OutputStream with
486        indentation.
487   
488        @param output a stream into which the XML-encoded data is written
489        @param indenter an object that creates indentation strings'''
490        raise NotImplementedError()
491
492                   
493class Effect(XacmlBase):
494    def __str__(self):
495        raise NotImplementedError()
496         
497class DenyEffect(Effect):
498    def __str__(self):
499        return 'deny'
500         
501class PermitEffect(Effect):
502    def __str__(self):
503        return 'permit'
504
505class Rule(XacmlBase):
506    '''Consists of a condition, an effect, and a target.
507    '''
508    def __init__(self):
509        # Conditions are statements about attributes that upon evaluation
510        # return either True, False, or Indeterminate.
511        self.conditions = []
512       
513        # Effect is the intended consequence of the satisfied rule. It can
514        # either take the value Permit or Deny.
515        self.effect = DenyEffect()
516     
517        # Target, as in the case of a policy, helps in determining whether or
518        # not a rule is relevant for a request. The mechanism for achieving
519        # this is also similar to how it is done in the case of a target for a
520        # policy.
521        self.target = Target()
522         
523         
524class Request(XacmlBase):
525    '''XACML Request XacmlBase
526   
527    TODO: refactor from this initial placeholder'''
528    def __init__(self):
529          self.subject = Subject()
530          self.resource = Resource()
531          self.action = Action()
532          self.environment = Environment()
533 
534class PEP(XacmlBase):
535    pass
536         
537class PDP(PDPInterface):
538    '''Modify PDPInterface to use the four XACML request designators: subject,
539    resource, action and environment
540   
541    This is an initial iteration toward a complete XACML implementation'''
542    def __init__(self, *arg, **kw):
543          pass
544   
545    def accessPermitted(self, request):
546          '''Make access control decision - override this in a derived class to
547          implement the decision logic but this method may be called within
548          the derived method to check input types
549         
550          @param subject: entity making the request e.g. user or user agent
551          @type subject: Subject
552          @param resource: resource to be accessed
553          @type resource: Resource
554          @param action: action to be carried out on the resource
555          @type action: Action
556          @param environ: environment settings
557          @type environ: Environment
558          @raise TypeError: incorrect inputs
559          '''
560          if not isinstance(subject, Subject):
561              raise TypeError("Input subject must of type %r" % Subject)
562
563          if not isinstance(resource, Resource):
564              raise TypeError("Input resource must of type %r" % Resource)
565
566          if not isinstance(action, Action):
567              raise TypeError("Input action must of type %r" % Action)
568
569          if not isinstance(environment, Environment):
570              raise TypeError("Input environment must of type %r" % Environment)
571         
572          # Default to denied
573          return False
574
575
576class RuleCombiningAlg(XacmlBase):
577    id = None
578
579class DenyOverrides(RuleCombiningAlg):
580   '''Deny-overrides: If any rule evaluates to Deny, then the final
581   authorization decision is also Deny.'''
582   id = 'Deny-overrides'
583   
584class OrderedDenyOverrides(RuleCombiningAlg):
585    '''Ordered-deny-overrides: Same as deny-overrides, except the order in
586    which relevant rules are evaluated is the same as the order in which they
587    are added in the policy.'''
588    id = 'Ordered-deny-overrides'
589   
590class PermitOverrides(RuleCombiningAlg):
591    '''Permit-overrides: If any rule evaluates to Permit, then the final
592    authorization decision is also Permit.'''
593   
594class OrderedPermitOverrides(RuleCombiningAlg):
595    '''Ordered-permit-overrides: Same as permit-overrides, except the order in
596    which relevant rules are evaluated is the same as the order in which they
597    are added in the policy.'''
598    id = 'Ordered-permit-overrides'
599   
600class FirstApplicable(RuleCombiningAlg):
601    '''First-applicable: The result of the first relevant rule encountered is
602    the final authorization decision as well.'''
603    id = 'First-applicable'
604
605
606class EvaluationCtx(object):
607
608    #
609    # The standard URI for listing a resource's id
610    #
611    RESOURCE_ID ="urn:oasis:names:tc:xacml:1.0:resource:resource-id"
612
613    #
614    # The standard URI for listing a resource's scope
615    #
616    RESOURCE_SCOPE = "urn:oasis:names:tc:xacml:1.0:resource:scope"
617
618    #
619    # Resource scope of Immediate (only the given resource)
620    #
621    SCOPE_IMMEDIATE = 0
622
623    #
624    # Resource scope of Children (the given resource and its direct
625    # children)
626    #
627    SCOPE_CHILDREN = 1
628
629    #
630    # Resource scope of Descendants (the given resource and all descendants
631    # at any depth or distance)
632    #
633    SCOPE_DESCENDANTS = 2
634   
635    def getRequestRoot(self):
636        '''Returns the DOM root of the original RequestType XML document, if
637        this context is backed by an XACML Request. If this context is not
638        backed by an XML representation, then an exception is thrown.'''
639        raise NotImplementedError()
640
641    def getResourceId(self):
642        '''Returns the identifier for the resource being requested.'''
643        raise NotImplementedError()
644
645    def getScope(self):
646        '''Returns the resource scope, which will be one of the three fields
647        denoting Immediate, Children, or Descendants.'''
648        raise NotImplementedError()
649
650    def setResourceId(self, resourceId):
651        '''Changes the value of the resource-id attribute in this context. This
652        is useful when you have multiple resources (ie, a scope other than
653        IMMEDIATE), and you need to keep changing only the resource-id to
654        evaluate the different effective requests.'''
655        raise NotImplementedError()
656
657    def getCurrentTime(self):
658        '''Returns the cached value for the current time. If the value has
659        never been set by a call to <code>setCurrentTime</code>, or if caching
660        is not enabled in this instance, then this will return null.'''
661        raise NotImplementedError()
662
663    def setCurrentTime(self, currentTime):
664        '''Sets the current time for this evaluation. If caching is not enabled
665        for this instance then the value is ignored.
666     
667        @param currentTime the dynamically resolved current time'''
668        raise NotImplementedError()
669
670    def getCurrentDate(self):
671        '''Returns the cached value for the current date. If the value has
672        never been set by a call to <code>setCurrentDate</code>, or if caching
673        is not enabled in this instance, then this will return null.'''
674        raise NotImplementedError()
675
676    def setCurrentDate(self, currentDate):
677        '''Sets the current date for this evaluation. If caching is not enabled
678        for this instance then the value is ignored.'''
679        raise NotImplementedError()
680
681    def getCurrentDateTime(self):
682        '''Returns the cached value for the current dateTime. If the value has
683        never been set by a call to <code>setCurrentDateTime</code>, or if
684        caching is not enabled in this instance, then this will return null.
685        '''
686        raise NotImplementedError()
687
688    def setCurrentDateTime(self, currentDateTime):
689        '''Sets the current dateTime for this evaluation. If caching is not
690        enabled for this instance then the value is ignored.
691     
692        @param currentDateTime the dynamically resolved current dateTime'''
693        raise NotImplementedError()
694
695    def getSubjectAttribute(self, type, id, category):
696        '''Returns available subject attribute value(s) ignoring the issuer.
697     
698        @param type the type of the attribute value(s) to find
699        @param id the id of the attribute value(s) to find
700        @param category the category the attribute value(s) must be in
701     
702        @return a result containing a bag either empty because no values were
703        found or containing at least one value, or status associated with an
704        Indeterminate result'''
705        raise NotImplementedError()
706
707    def getSubjectAttribute(self, type, id, issuer, category):
708        '''Returns available subject attribute value(s).
709     
710        @param type the type of the attribute value(s) to find
711        @param id the id of the attribute value(s) to find
712        @param issuer the issuer of the attribute value(s) to find or null
713        @param category the category the attribute value(s) must be in
714     
715        @return a result containing a bag either empty because no values were
716        found or containing at least one value, or status associated with an
717        Indeterminate result'''
718        raise NotImplementedError()
719   
720    def getResourceAttribute(self, type, id, issuer):
721        '''Returns available resource attribute value(s).
722     
723        @param type the type of the attribute value(s) to find
724        @param id the id of the attribute value(s) to find
725        @param issuer the issuer of the attribute value(s) to find or null
726     
727        @return a result containing a bag either empty because no values were
728        found or containing at least one value, or status associated with an
729        Indeterminate result'''
730        raise NotImplementedError()
731
732    def getActionAttribute(self, type, id, issuer):
733        '''Returns available action attribute value(s).
734     
735        @param type the type of the attribute value(s) to find
736        @param id the id of the attribute value(s) to find
737        @param issuer the issuer of the attribute value(s) to find or null
738     
739        @return a result containing a bag either empty because no values were
740        found or containing at least one value, or status associated with an
741        Indeterminate result'''
742        raise NotImplementedError()
743
744    def getEnvironmentAttribute(self, type, id, issuer):
745        '''Returns available environment attribute value(s).
746     
747        @param type the type of the attribute value(s) to find
748        @param id the id of the attribute value(s) to find
749        @param issuer the issuer of the attribute value(s) to find or null
750     
751        @return a result containing a bag either empty because no values were
752        found or containing at least one value, or status associated with an
753        Indeterminate result'''
754        raise NotImplementedError()
755
756    def getAttribute(self, contextPath, namespaceNode, type, xpathVersion):
757        '''Returns the attribute value(s) retrieved using the given XPath
758        expression.
759     
760        @param contextPath the XPath expression to search
761        @param namespaceNode the DOM node defining namespace mappings to use,
762                            or null if mappings come from the context root
763        @param type the type of the attribute value(s) to find
764        @param xpathVersion the version of XPath to use
765     
766        @return a result containing a bag either empty because no values were
767       
768        found or containing at least one value, or status associated with an
769        Indeterminate result'''
770        raise NotImplementedError()
Note: See TracBrowser for help on using the repository browser.