source: TI12-security/trunk/NDG_XACML/ndg/xacml/core/target.py @ 6806

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDG_XACML/ndg/xacml/core/target.py@6806
Revision 6806, 8.1 KB checked in by pjkersha, 10 years ago (diff)

Moving matching and rule evaluation code out of the PDP class and into the relevant classes they pertain to e.g. target matching moved to Target class match method and so on.

Line 
1'''
2Created on 24 Feb 2010
3
4@author: pjkersha
5'''
6from ndg.xacml.utils import TypedList
7"""NDG Security Target type definition
8
9NERC DataGrid Project
10"""
11__author__ = "P J Kershaw"
12__date__ = "25/02/10"
13__copyright__ = "(C) 2010 Science and Technology Facilities Council"
14__contact__ = "Philip.Kershaw@stfc.ac.uk"
15__license__ = "BSD - see LICENSE file in top-level directory"
16__contact__ = "Philip.Kershaw@stfc.ac.uk"
17__revision__ = "$Id: $"
18import logging
19log = logging.getLogger(__name__)
20
21from ndg.xacml.core import XacmlCoreBase
22from ndg.xacml.core.action import Action
23from ndg.xacml.core.resource import Resource
24from ndg.xacml.core.subject import Subject
25from ndg.xacml.core.environment import Environment
26
27
28class Target(XacmlCoreBase):
29    """XACML Target element"""
30    ELEMENT_LOCAL_NAME = "Target"
31    SUBJECTS_ELEMENT_LOCAL_NAME = "Subjects"
32    ACTIONS_ELEMENT_LOCAL_NAME = "Actions"
33    RESOURCES_ELEMENT_LOCAL_NAME = "Resources"
34    ENVIRONMENTS_ELEMENT_LOCAL_NAME = "Environments"
35    CHILD_ATTRS = ('subjects', 'resources', 'actions', 'environments')
36   
37    __slots__ = ('__subjects', '__resources', '__actions', '__environments')
38   
39    def __init__(self):
40        """Initial attributes"""
41        self.__subjects = TypedList(Subject)
42        self.__resources = TypedList(Resource)
43        self.__actions = TypedList(Action)
44        self.__environments = TypedList(Environment)
45   
46    @property
47    def subjects(self):
48        return self.__subjects
49   
50    @property
51    def resources(self):
52        return self.__resources
53   
54    @property
55    def actions(self):
56        return self.__actions
57   
58    @property
59    def environments(self):
60        return self.__environments
61           
62    def match(self, request):
63        """Generic method to match a <Target> element to the request context
64       
65        @param target: XACML target element
66        @type target: ndg.xacml.core.target.Target
67        @param request: XACML request context
68        @type request: ndg.xacml.core.context.request.Request
69        @return: True if request context matches the given target,
70        False otherwise
71        @rtype: bool
72        """
73       
74        # From section 5.5 of the XACML 2.0 Core Spec:
75        #
76        # For the parent of the <Target> element to be applicable to the
77        # decision request, there MUST be at least one positive match between
78        # each section of the <Target> element and the corresponding section of
79        # the <xacml-context:Request> element.
80        #
81        # Also, 7.6:
82        #
83        # The target value SHALL be "Match" if the subjects, resources, actions
84        # and environments specified in the target all match values in the
85        # request context.
86        statusValues = [False]*len(self.__class__.CHILD_ATTRS) 
87       
88        # Iterate for target subjects, resources, actions and environments
89        # elements
90        for i, attrName in enumerate(self.__class__.CHILD_ATTRS):
91            # If any one of the <Target> children is missing then it counts as
92            # a match e.g. for <Subjects> child element - Section 5.5:
93            #
94            # <Subjects> [Optional] Matching specification for the subject
95            # attributes in the context. If this element is missing,
96            # then the target SHALL match all subjects.
97            targetElem = getattr(self, attrName)
98            if len(targetElem) == 0:
99                statusValues[i] = True
100                continue
101           
102            # Iterate over each for example, subject in the list of subjects:
103            # <Target>
104            #     <Subjects>
105            #          <Subject>
106            #              ...
107            #          </Subject>
108            #          <Subject>
109            #              ...
110            #          </Subject>
111            #     ...
112            # or resource in the list of resources and so on
113            for targetSubElem in targetElem:
114               
115                # For the given subject/resource/action/environment check for a
116                # match with the equivalent in the request
117                requestElem = getattr(request, attrName) 
118                for requestSubElem in requestElem:
119                    if self._matchChild(targetSubElem, requestSubElem):
120                        # Within the list of e.g. subjects if one subject
121                        # matches then this counts as a subject match overall
122                        # for this target
123                        statusValues[i] = True
124 
125        # Target matches if all the children (i.e. subjects, resources, actions
126        # and environment sections) have at least one match.  Otherwise it
127        # doesn't count as a match
128        return all(statusValues)
129   
130    def _matchChild(self, targetChild, requestChild):
131        """Match a request child element (a <Subject>, <Resource>, <Action> or
132        <Environment>) with the corresponding target's <Subject>, <Resource>,
133        <Action> or <Environment>.
134       
135        @param targetChild: Target Subject, Resource, Action or Environment
136        object
137        @type targetChild: ndg.xacml.core.TargetChildBase
138        @param requestChild: Request Subject, Resource, Action or Environment
139        object
140        @type requestChild: ndg.xacml.core.context.RequestChildBase
141        @return: True if request context matches something in the target
142        @rtype: bool
143        @raise UnsupportedElementError: AttributeSelector processing is not
144        currently supported.  If an AttributeSelector is found in the policy,
145        this exception will be raised.
146        @raise UnsupportedStdFunctionError: policy references a function type
147        which is in the XACML spec. but is not supported by this implementation
148        @raise UnsupportedFunctionError: policy references a function type which
149        is not supported by this implementation
150        """
151        if targetChild is None:
152            # Default if target child is not set is to match all children
153            return True
154       
155        matchStatusValues = [True]*len(targetChild.matches)
156       
157        # Section 7.6
158        #
159        # A subject, resource, action or environment SHALL match a value in the
160        # request context if the value of all its <SubjectMatch>,
161        # <ResourceMatch>, <ActionMatch> or <EnvironmentMatch> elements,
162        # respectively, are "True".
163        #
164        # e.g. for <SubjectMatch>es in <Subject> ...
165        for childMatch, matchStatus in zip(targetChild.matches, 
166                                           matchStatusValues):
167           
168            matchStatusValues[i] = childMatch.evaluate(requestChild)
169           
170        # Any match => overall match     
171        return any(matchStatusValues)
172   
173               
174    def attributeDesignatorMatchFuncFactory(self,
175                                            matchFunc,
176                                            matchAttributeValue, 
177                                            attributeDesignator):
178        """Define a match function to match a given request attribute against
179        the input attribute value and AttributeDesignator defined in a policy
180        target
181        """           
182        attributeId = attributeDesignator.attributeId
183        dataType = attributeDesignator.dataType
184       
185        # Issuer is an optional match - see core spec. 7.2.4
186        issuer = attributeDesignator.issuer
187        if issuer is not None:
188            # Issuer found - set lambda to match this against the
189            # issuer setting in the request
190            _issuerMatch = lambda requestChildIssuer: (
191                                                issuer == requestChildIssuer)
192        else:
193            # No issuer set - lambda returns True regardless
194            _issuerMatch = lambda requestChildIssuer: True
195       
196       
197        _attributeMatch = lambda attribute: (
198            any([matchFunc.evaluate(matchAttributeValue, attrVal) 
199                 for attrVal in attribute.attributeValues]) and
200            attribute.attributeId == attributeId and
201            attribute.dataType == dataType and
202            _issuerMatch(attribute.issuer)
203        )
204       
205        return _attributeMatch
Note: See TracBrowser for help on using the repository browser.