Package ndg :: Package xacml :: Package core :: Module rule_combining_alg
[hide private]

Source Code for Module ndg.xacml.core.rule_combining_alg

  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  # Rule Combining algorithms from the XACML spec. 
 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  ) 
34 35 36 -class RuleCombiningAlgInterface(object):
37 """Interface class for XAML rule combining algorithms""" 38 39 @abstractmethod
40 - def evaluate(self, rules, context):
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
55 56 -class DenyOverridesRuleCombiningAlg(RuleCombiningAlgInterface):
57 """Deny overrides rule combining algorithm""" 58
59 - def evaluate(self, rules, context):
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
107 108 -class PermitOverridesRuleCombiningAlg(RuleCombiningAlgInterface):
109 """Implementation of permit overrides XACML rule combining algorithm""" 110
111 - def evaluate(self, rules, context):
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
169 170 -class FirstApplicableRuleCombiningAlg(RuleCombiningAlgInterface):
171 """Implementation of first applicable XACML rule combining algorithm""" 172
173 - def evaluate(self, rules, context):
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
210 211 -class RuleCombiningAlgClassFactory(object):
212 """Class Factory mapping Rule Combining Algorithm identifiers to their 213 class implementations""" 214 215 # All algorithms are not implemented by default(!) 216 DEFAULT_MAP = {}.fromkeys(ALGORITHMS, NotImplemented) 217 218 # Permit overrides is the only one currently implemented 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
229 - def __init__(self, map=DEFAULT_MAP):
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
237 - def __call__(self, identifier):
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