1 """NDG XACML Condition type definition
2
3 NERC DataGrid
4 """
5 __author__ = "P J Kershaw"
6 __date__ = "15/04/10"
7 __copyright__ = "(C) 2010 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: rule_combining_alg.py 7955 2011-12-21 18:29:45Z rwilkinson $"
12 import logging
13 log = logging.getLogger(__name__)
14
15 from abc import abstractmethod
16
17 from ndg.xacml.core.context.result import Decision
18
19
20
21 ALGORITHMS = (
22 'urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides',
23 'urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:deny-overrides',
24 'urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:permit-overrides',
25 'urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:permit-overrides',
26 'urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable',
27 'urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:first-applicable',
28 'urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:only-one-applicable',
29 'urn:oasis:names:tc:xacml:1.1:rule-combining-algorithm:ordered-deny-overrides',
30 'urn:oasis:names:tc:xacml:1.1:policy-combining-algorithm:ordered-deny-overrides',
31 'urn:oasis:names:tc:xacml:1.1:rule-combining-algorithm:ordered-permit-overrides',
32 'urn:oasis:names:tc:xacml:1.1:policy-combining-algorithm:ordered-permit-overrides',
33 )
37 """Interface class for XAML rule combining algorithms"""
38
39 @abstractmethod
41 """Combine the input rule results to make an access control decision
42 based. Derived classes must implement this method. This implementation
43 returns indeterminate result.
44
45 @param rules: rules from the policy. Decisions from these will be put
46 together into a single decision by this algorithm
47 @type rules: TypedList(<ndg.xacml.core.rule.Rule>)
48 @param context: request context to apply to the rules
49 @type context: ndg.xacml.core.request.Request
50 @return: resulting overall access control decision
51 @rtype: ndg.xacml.core.context.result.Decision
52 """
53 return Decision.INDETERMINATE
54
57 """Deny overrides rule combining algorithm"""
58
60 """Combine the input rule results to make an access control decision.
61 Implementation taken direct from XACML 2.0 spec. pseudo code - Section
62 C.1 Deny Overrides
63
64 @param rules: rules from the policy. Decisions from these will be put
65 together into a single decision by this algorithm
66 @type rules: TypedList(<ndg.xacml.core.rule.Rule>)
67 @param context: request context to apply to the rules
68 @type context: ndg.xacml.core.request.Request
69 @return: resulting overall access control decision
70 @rtype: ndg.xacml.core.context.result.Decision
71 """
72 atLeastOneError = False
73 potentialDeny = False
74 atLeastOnePermit = False
75
76 for rule in rules:
77 decision = rule.evaluate(context)
78 if decision == Decision.DENY:
79 return Decision.DENY
80
81 if decision == Decision.PERMIT:
82 atLeastOnePermit = True
83 continue
84
85 if decision == Decision.NOT_APPLICABLE:
86 continue
87
88 if decision == Decision.INDETERMINATE:
89 atLeastOneError = True
90
91 if rule.effect.value == Decision.DENY:
92 potentialDeny = True
93
94 continue
95
96 if potentialDeny:
97 return Decision.INDETERMINATE
98
99 elif atLeastOnePermit:
100 return Decision.PERMIT
101
102 elif atLeastOneError:
103 return Decision.INDETERMINATE
104 else:
105 return Decision.NOT_APPLICABLE
106
109 """Implementation of permit overrides XACML rule combining algorithm"""
110
112 """Combine the input rule results to make an access control decision.
113 Implementation taken direct from XACML 2.0 spec. pseudo code - Section
114 C.3
115
116 @param rules: rules from the policy. Decisions from these will be put
117 together into a single decision by this algorithm
118 @type rules: TypedList(<ndg.xacml.core.rule.Rule>)
119 @param context: request context to apply to the rules
120 @type context: ndg.xacml.core.request.Request
121 @return: resulting overall access control decision
122 @rtype: ndg.xacml.core.context.result.Decision
123 """
124 atLeastOneError = False
125 potentialPermit = False
126 atLeastOneDeny = False
127
128 for rule in rules:
129 decision = rule.evaluate(context)
130 if decision == Decision.DENY:
131 atLeastOneDeny = True
132 continue
133
134 if decision == Decision.PERMIT:
135 log.debug("Rule %r permits, returning overall permit decision",
136 rule.id)
137 return Decision.PERMIT
138
139 if decision == Decision.NOT_APPLICABLE:
140 continue
141
142 if decision == Decision.INDETERMINATE:
143 atLeastOneError = True
144
145 if rule.effect.value == Decision.PERMIT_STR:
146 potentialPermit = True
147
148 continue
149
150 if potentialPermit:
151 log.debug('Rule found with potential permit but it evaluates to '
152 'indeterminate, returning overall indeterminate decision')
153 return Decision.INDETERMINATE
154
155 if atLeastOneDeny:
156 log.debug('At least one rule with a deny decision found, returning '
157 'overall deny decision')
158 return Decision.DENY
159
160 if atLeastOneError:
161 log.debug('At least one rule with an error found, returning '
162 'overall indeterminate decision')
163 return Decision.INDETERMINATE
164
165 log.debug('No rules were applicable to the request, returning '
166 'overall not applicable decision')
167 return Decision.NOT_APPLICABLE
168
171 """Implementation of first applicable XACML rule combining algorithm"""
172
174 """Combine the input rule results to make an access control decision.
175 Implementation taken direct from XACML 2.0 spec. pseudo code - Section
176 C.5
177
178 @param rules: rules from the policy. Decisions from these will be put
179 together into a single decision by this algorithm
180 @type rules: TypedList(<ndg.xacml.core.rule.Rule>)
181 @param context: request context to apply to the rules
182 @type context: ndg.xacml.core.request.Request
183 @return: resulting overall access control decision
184 @rtype: ndg.xacml.core.context.result.Decision
185 """
186 for rule in rules:
187 decision = rule.evaluate(context)
188 if decision == Decision.DENY:
189 log.debug("Rule %r denies, returning overall deny decision",
190 rule.id)
191 return Decision.DENY
192
193 if decision == Decision.PERMIT:
194 log.debug("Rule %r permits, returning overall permit decision",
195 rule.id)
196 return Decision.PERMIT
197
198 if decision == Decision.NOT_APPLICABLE:
199 continue
200
201 if decision == Decision.INDETERMINATE:
202 log.debug("Rule %r is indeterminate, returning overall "
203 "indeterminate decision", rule.id)
204 return Decision.INDETERMINATE
205
206 log.debug('No rules were applicable to the request, returning '
207 'overall not applicable decision')
208 return Decision.NOT_APPLICABLE
209
212 """Class Factory mapping Rule Combining Algorithm identifiers to their
213 class implementations"""
214
215
216 DEFAULT_MAP = {}.fromkeys(ALGORITHMS, NotImplemented)
217
218
219 DEFAULT_MAP.update({
220 'urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides':
221 DenyOverridesRuleCombiningAlg,
222 'urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:permit-overrides':
223 PermitOverridesRuleCombiningAlg,
224 'urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable':
225 FirstApplicableRuleCombiningAlg
226 })
227 __slots__ = ('__map',)
228
230 """Initialise mapping of identifiers to class implementations
231
232 @param map: mapping of rule combining algorithms IDs to classes. Set
233 this to override the default taken from the DEFAULT_MAP class variable
234 """
235 self.__map = map
236
238 """Return the class for a given Rule Combining Algorithm identifier
239 @param identifier: XACML rule combining algorithm urn
240 @type identifier: basestring
241 @return: rule combining class corresponding to the given input
242 identifier
243 @rtype: RuleCombiningAlgInterface derived type or NoneType if no match
244 is found or NotImplementedType if the identifier corresponds to a valid
245 XACML rule combining algorithm but is not supported in this
246 implementation
247 """
248 return self.__map.get(identifier)
249