Changeset 5168 for TI12-security
- Timestamp:
- 03/04/09 17:14:44 (12 years ago)
- Location:
- TI12-security/trunk/python
- Files:
-
- 3 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/xacml/__init__.py
r5165 r5168 14 14 log = logging.getLogger(__name__) 15 15 16 from ndg.security.common.authz.xacml.cond import FunctionFactory 16 #from ndg.security.common.authz.xacml.cond import FunctionFactory 17 import ndg.security.common.authz.xacml.cond 18 class FunctionFactory: 19 pass 20 17 21 18 22 # For parsing: ElementTree helpers … … 265 269 266 270 def match(self, context): 267 '''determines whether this <code>TargetMatch</code>matches271 '''determines whether this TargetMatch matches 268 272 the input request (whether it is applicable) 269 273 … … 348 352 349 353 def encode(self, output, indenter=None): 350 '''Encodes this TargetMatch </code>into its XML representation351 and writes this encoding to the given <code>OutputStream</code>with no354 '''Encodes this TargetMatch into its XML representation 355 and writes this encoding to the given OutputStream with no 352 356 indentation. 353 357 @param output a stream into which the XML-encoded data is written''' … … 372 376 self.attributeValue = attributeValue 373 377 self.indeterminate = indeterminate 374 375 376 class Evaluatable(XacmlBase): 377 '''Generic interface that is implemented by all objects that can appear in 378 an ApplyType. This lets the evaluation code of Apply and 379 functions iterate through their members and evaluate them, working only 380 on the returned values or errors.''' 381 382 def evaluate(self, context): 383 '''Evaluates the object using the given context, and either returns an 384 error or a resulting value. 385 386 @param context the representation of the request 387 @return the result of evaluation''' 388 raise NotImplementedError() 389 390 def getType(self): 391 '''Get the type of this object. This may be the data type of an 392 Attribute or the return type of an 393 AttributeDesignator, etc. 394 395 @return the type of data represented by this object''' 396 raise NotImplementedError() 397 398 def evaluatesToBag(self): 399 '''Tells whether evaluation will return a bag or a single value. 400 401 @return true if evaluation will return a bag, false otherwise''' 402 raise NotImplementedError() 403 404 def getChildren(self): 405 '''Returns all children, in order, of this element in the Condition 406 tree, or en empty set if this element has no children. In XACML 1.x, 407 only the ApplyType ever has children. 408 409 @return a list of Evaluatables''' 410 raise NotImplementedError() 411 412 def encode(self, output, indenter=None): 413 '''Encodes this Evaluatable into its XML representation and 414 writes this encoding to the given OutputStream with 415 indentation. 416 417 @param output a stream into which the XML-encoded data is written 418 @param indenter an object that creates indentation strings''' 419 raise NotImplementedError() 420 421 378 379 422 380 class Effect(XacmlBase): 423 381 def __str__(self): 424 382 raise NotImplementedError() 425 383 384 426 385 class DenyEffect(Effect): 427 386 def __str__(self): … … 456 415 457 416 class Attribute(XacmlBase): 458 def __init__(self, id, type=None, issuer=None, issueInstant=None, value=None): 417 def __init__(self, id, type=None, issuer=None, issueInstant=None, 418 value=None): 459 419 self.id = id 460 420 self.type = type or value.__class__ … … 573 533 def getCurrentTime(self): 574 534 '''Returns the cached value for the current time. If the value has 575 never been set by a call to <code>setCurrentTime</code>, or if caching535 never been set by a call to setCurrentTime, or if caching 576 536 is not enabled in this instance, then this will return null.''' 577 537 raise NotImplementedError() … … 586 546 def getCurrentDate(self): 587 547 '''Returns the cached value for the current date. If the value has 588 never been set by a call to <code>setCurrentDate</code>, or if caching548 never been set by a call to setCurrentDate, or if caching 589 549 is not enabled in this instance, then this will return null.''' 590 550 raise NotImplementedError() … … 597 557 def getCurrentDateTime(self): 598 558 '''Returns the cached value for the current dateTime. If the value has 599 never been set by a call to <code>setCurrentDateTime</code>, or if559 never been set by a call to setCurrentDateTime, or if 600 560 caching is not enabled in this instance, then this will return null. 601 561 ''' … … 685 645 Indeterminate result''' 686 646 raise NotImplementedError() 687 688 689 class Apply(Evaluatable):690 '''Represents the XACML ApplyType and ConditionType XML types.'''691 692 def __init__(self, function, evals, bagFunction=None, isCondition=False):693 '''Constructs an Apply object. Throws an694 IllegalArgumentException if the given parameter list695 isn't valid for the given function.696 697 @param function the Function to use in evaluating the elements in the698 apply699 @param evals the contents of the apply which will be the parameters700 to the function, each of which is an Evaluatable701 @param bagFunction the higher-order function to use702 @param isCondition Rrue if this Apply is a Condition, False otherwise703 '''704 705 # check that the given inputs work for the function706 inputs = evals707 if bagFunction is not None:708 inputs = [bagFunction]709 inputs += evals710 711 function.checkInputs(inputs)712 713 # if everything checks out, then store the inputs714 self.function = function715 self.evals = tuple(evals)716 self.bagFunction = bagFunction717 self.isCondition = isCondition718 719 720 @staticmethod721 def getConditionInstance(root, xpathVersion):722 '''Returns an instance of an Apply based on the given DOM723 root node. This will actually return a special kind of724 Apply, namely an XML ConditionType, which is the root725 of the condition logic in a RuleType. A ConditionType is the same726 as an ApplyType except that it must use a FunctionId that returns727 a boolean value.728 729 @param root the DOM root of a ConditionType XML type730 @param xpathVersion the XPath version to use in any selectors or XPath731 functions, or null if this is unspecified (ie, not732 supplied in the defaults section of the policy)733 734 '''735 raise NotImplementedError()736 737 def getInstance(self,738 root,739 factory=None,740 isCondition=False,741 xpathVersion=None):742 '''Returns an instance of Apply based on the given DOM root.743 744 @param root the DOM root of an ApplyType XML type745 @param xpathVersion the XPath version to use in any selectors or XPath746 functions, or null if this is unspecified (ie, not747 supplied in the defaults section of the policy)'''748 749 raise NotImplementedError()750 751 @staticmethod752 def getFunction(root, version, factory):753 '''Helper method that tries to get a function instance'''754 raise NotImplementedError()755 756 def getFunction(self):757 '''Returns the Function used by this Apply.758 759 @return the Function'''760 return function761 762 def getChildren(self):763 '''Returns the List of children for this Apply.764 The List contains Evaluatables. The list is765 unmodifiable, and may be empty.766 767 @return a List of Evaluatables'''768 return self.evals769 770 def getHigherOrderFunction(self):771 '''Returns the higher order bag function used by this Apply772 if it exists, or null if no higher order function is used.773 774 @return the higher order Function or null'''775 return self.bagFunction776 777 def isCondition(self):778 '''Returns whether or not this ApplyType is actually a ConditionType.779 780 @return whether or not this represents a ConditionType'''781 return isCondition782 783 def evaluate(self, context):784 '''Evaluates the apply object using the given function. This will in785 turn call evaluate on all the given parameters, some of which may be786 other Apply objects.787 788 @param context the representation of the request789 790 @return the result of trying to evaluate this apply object'''791 parameters = self.evals792 793 # see if there is a higher-order function in here794 if bagFunction != None:795 # this is a special case, so we setup the parameters, starting796 # with the function797 parameters = [bagFunction]798 799 # now we evaluate all the parameters, returning INDETERMINATE800 # if that's what any of them return, and otherwise tracking801 # all the AttributeValues that get returned802 for eval in self.evals:803 result = eval.evaluate(context)804 805 # in a higher-order case, if anything is INDETERMINATE, then806 # we stop right away807 if result.indeterminate():808 return result809 810 parameters.add(result.getAttributeValue())811 812 # now we can call the base function813 return function.evaluate(parameters, context)814 815 def getType(self):816 '''Returns the type of attribute that this object will return on a call817 to evaluate. In practice, this will always be the same as818 the result of calling getReturnType on the function used819 by this object.820 821 @return the type returned by evaluate'''822 return self.function.getReturnType()823 824 def evaluatesToBag(self):825 '''Returns whether or not the Function will return a bag826 of values on evaluation.827 828 @return true if evaluation will return a bag of values, false otherwise829 '''830 return self.function.returnsBag()831 832 def encode(self, output, indenter):833 '''Encodes this Apply into its XML representation and834 writes this encoding to the given OutputStream with835 indentation.836 837 @param output a stream into which the XML-encoded data is written838 @param indenter an object that creates indentation strings'''839 raise NotImplementedError() -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/xacml/cond.py
r5165 r5168 14 14 15 15 from ndg.security.common.utils import UniqList 16 17 class FunctionBase(object): 16 from ndg.security.common.authz.xacml.attr import AnyURIAttribute, \ 17 Base64BinaryAttribute, BooleanAttribute, DateAttribute, DateTimeAttribute,\ 18 DayTimeDurationEqual, DoubleAttribute, HexBinaryAttribute, \ 19 IntegerAttribute, RFC822NameAttribute, StringAttribute, TimeAttribute, \ 20 X500NameAttribute, YearMonthDurationAttribute 21 22 23 class Evaluatable(object): 24 '''Generic interface that is implemented by all objects that can appear in 25 an ApplyType. This lets the evaluation code of Apply and 26 functions iterate through their members and evaluate them, working only 27 on the returned values or errors.''' 28 29 def evaluate(self, context): 30 '''Evaluates the object using the given context, and either returns an 31 error or a resulting value. 32 33 @param context the representation of the request 34 @return the result of evaluation''' 35 raise NotImplementedError() 36 37 def getType(self): 38 '''Get the type of this object. This may be the data type of an 39 Attribute or the return type of an 40 AttributeDesignator, etc. 41 42 @return the type of data represented by this object''' 43 raise NotImplementedError() 44 45 def evaluatesToBag(self): 46 '''Tells whether evaluation will return a bag or a single value. 47 48 @return true if evaluation will return a bag, false otherwise''' 49 raise NotImplementedError() 50 51 def getChildren(self): 52 '''Returns all children, in order, of this element in the Condition 53 tree, or en empty set if this element has no children. In XACML 1.x, 54 only the ApplyType ever has children. 55 56 @return a list of Evaluatables''' 57 raise NotImplementedError() 58 59 def encode(self, output, indenter=None): 60 '''Encodes this Evaluatable into its XML representation and 61 writes this encoding to the given OutputStream with 62 indentation. 63 64 @param output a stream into which the XML-encoded data is written 65 @param indenter an object that creates indentation strings''' 66 raise NotImplementedError() 67 68 69 class Apply(Evaluatable): 70 '''Represents the XACML ApplyType and ConditionType XML types.''' 71 72 def __init__(self, function, evals, bagFunction=None, isCondition=False): 73 '''Constructs an Apply object. Throws an 74 IllegalArgumentException if the given parameter list 75 isn't valid for the given function. 76 77 @param function the Function to use in evaluating the elements in the 78 apply 79 @param evals the contents of the apply which will be the parameters 80 to the function, each of which is an Evaluatable 81 @param bagFunction the higher-order function to use 82 @param isCondition Rrue if this Apply is a Condition, False otherwise 83 ''' 84 85 # check that the given inputs work for the function 86 inputs = evals 87 if bagFunction is not None: 88 inputs = [bagFunction] 89 inputs += evals 90 91 function.checkInputs(inputs) 92 93 # if everything checks out, then store the inputs 94 self.function = function 95 self.evals = tuple(evals) 96 self.bagFunction = bagFunction 97 self.isCondition = isCondition 98 99 100 @staticmethod 101 def getConditionInstance(root, xpathVersion): 102 '''Returns an instance of an Apply based on the given DOM 103 root node. This will actually return a special kind of 104 Apply, namely an XML ConditionType, which is the root 105 of the condition logic in a RuleType. A ConditionType is the same 106 as an ApplyType except that it must use a FunctionId that returns 107 a boolean value. 108 109 @param root the DOM root of a ConditionType XML type 110 @param xpathVersion the XPath version to use in any selectors or XPath 111 functions, or null if this is unspecified (ie, not 112 supplied in the defaults section of the policy) 113 114 ''' 115 raise NotImplementedError() 116 117 def getInstance(self, 118 root, 119 factory=None, 120 isCondition=False, 121 xpathVersion=None): 122 '''Returns an instance of Apply based on the given DOM root. 123 124 @param root the DOM root of an ApplyType XML type 125 @param xpathVersion the XPath version to use in any selectors or XPath 126 functions, or null if this is unspecified (ie, not 127 supplied in the defaults section of the policy)''' 128 129 raise NotImplementedError() 130 131 @staticmethod 132 def getFunction(root, version, factory): 133 '''Helper method that tries to get a function instance''' 134 raise NotImplementedError() 135 136 def getFunction(self): 137 '''Returns the Function used by this Apply. 138 139 @return the Function''' 140 return function 141 142 def getChildren(self): 143 '''Returns the List of children for this Apply. 144 The List contains Evaluatables. The list is 145 unmodifiable, and may be empty. 146 147 @return a List of Evaluatables''' 148 return self.evals 149 150 def getHigherOrderFunction(self): 151 '''Returns the higher order bag function used by this Apply 152 if it exists, or null if no higher order function is used. 153 154 @return the higher order Function or null''' 155 return self.bagFunction 156 157 def isCondition(self): 158 '''Returns whether or not this ApplyType is actually a ConditionType. 159 160 @return whether or not this represents a ConditionType''' 161 return isCondition 162 163 def evaluate(self, context): 164 '''Evaluates the apply object using the given function. This will in 165 turn call evaluate on all the given parameters, some of which may be 166 other Apply objects. 167 168 @param context the representation of the request 169 170 @return the result of trying to evaluate this apply object''' 171 parameters = self.evals 172 173 # see if there is a higher-order function in here 174 if bagFunction != None: 175 # this is a special case, so we setup the parameters, starting 176 # with the function 177 parameters = [bagFunction] 178 179 # now we evaluate all the parameters, returning INDETERMINATE 180 # if that's what any of them return, and otherwise tracking 181 # all the AttributeValues that get returned 182 for eval in self.evals: 183 result = eval.evaluate(context) 184 185 # in a higher-order case, if anything is INDETERMINATE, then 186 # we stop right away 187 if result.indeterminate(): 188 return result 189 190 parameters.add(result.getAttributeValue()) 191 192 # now we can call the base function 193 return function.evaluate(parameters, context) 194 195 def getType(self): 196 '''Returns the type of attribute that this object will return on a call 197 to evaluate. In practice, this will always be the same as 198 the result of calling getReturnType on the function used 199 by this object. 200 201 @return the type returned by evaluate''' 202 return self.function.getReturnType() 203 204 def evaluatesToBag(self): 205 '''Returns whether or not the Function will return a bag 206 of values on evaluation. 207 208 @return true if evaluation will return a bag of values, false otherwise 209 ''' 210 return self.function.returnsBag() 211 212 def encode(self, output, indenter): 213 '''Encodes this Apply into its XML representation and 214 writes this encoding to the given OutputStream with 215 indentation. 216 217 @param output a stream into which the XML-encoded data is written 218 @param indenter an object that creates indentation strings''' 219 raise NotImplementedError() 220 221 class Function(object): 222 '''Interface that all functions in the system must implement.''' 223 224 def evaluate(self, inputs, context): 225 '''Evaluates the Function using the given inputs. 226 The List contains Evaluatables which are all 227 of the correct type if the Function has been created as 228 part of an Apply or TargetMatch, but which 229 may otherwise be invalid. Each parameter should be evaluated by the 230 Function, unless this is a higher-order function (in 231 which case the Apply has already evaluated the inputs 232 to check for any INDETERMINATE conditions), or the Function 233 doesn't need to evaluate all inputs to determine a result (as in the 234 case of the or function). The order of the List is 235 significant, so a Function should have a very good reason 236 if it wants to evaluate the inputs in a different order. 237 <p> 238 Note that if this is a higher-order function, like any-of, then 239 the first argument in the List will actually be a Function 240 object representing the function to apply to some bag. In this case, 241 the second and any subsequent entries in the list are 242 AttributeValue objects (no INDETERMINATE values are 243 allowed, so the function is not given the option of dealing with 244 attributes that cannot be resolved). A function needs to know if it's 245 a higher-order function, and therefore whether or not to look for 246 this case. Also, a higher-order function is responsible for checking 247 that the inputs that it will pass to the Function 248 provided as the first parameter are valid, ie. it must do a 249 checkInputs on its sub-function when 250 checkInputs is called on the higher-order function. 251 252 @param inputs the List of inputs for the function 253 @param context the representation of the request 254 255 @return a result containing the AttributeValue computed 256 when evaluating the function, or Status 257 specifying some error condition''' 258 raise NotImplementedError() 259 260 261 def getIdentifier(self): 262 '''Returns the identifier of this function as known by the factories. 263 In the case of the standard XACML functions, this will be one of the 264 URIs defined in the standard namespace. This function must always 265 return the complete namespace and identifier of this function. 266 267 @return the function's identifier''' 268 raise NotImplementedError() 269 270 def getReturnType(self): 271 '''Provides the type of AttributeValue that this function 272 returns from evaluate in a successful evaluation. 273 274 @return the type returned by this function 275 ''' 276 raise NotImplementedError() 277 278 def returnsBag(self): 279 '''Tells whether this function will return a bag of values or just a 280 single value. 281 282 @return true if evaluation will return a bag, false otherwise''' 283 raise NotImplementedError() 284 285 def checkInputs(self, inputs): 286 '''Checks that the given inputs are of the right types, in the right 287 order, and are the right number for this function to evaluate. If 288 the function cannot accept the inputs for evaluation, an 289 IllegalArgumentException is thrown. 290 291 @param inputs a list of Evaluatables, with the first argument being a 292 Function if this is a higher-order function 293 294 @throws TypeError if the inputs do match what the function accepts for 295 evaluation 296 ''' 297 raise NotImplementedError() 298 299 def checkInputsNoBag(self, inputs): 300 '''Checks that the given inputs are of the right types, in the right 301 order, and are the right number for this function to evaluate. If 302 the function cannot accept the inputs for evaluation, an 303 IllegalArgumentException is thrown. Unlike the other 304 checkInput method in this interface, this assumes that 305 the parameters will never provide bags of values. This is useful if 306 you're considering a target function which has a designator or 307 selector in its input list, but which passes the values from the 308 derived bags one at a time to the function, so the function doesn't 309 have to deal with the bags that the selector or designator 310 generates. 311 312 @param inputs a list of Evaluatables, with the first argument being a 313 Function if this is a higher-order function 314 315 @throws TypeError if the inputs do match what the function accepts for 316 evaluation''' 317 raise NotImplementedError() 318 319 320 class FunctionBase(Function): 18 321 FUNCTION_NS = "urn:oasis:names:tc:xacml:1.0:function:" 19 322 supportedIdentifiers = () … … 28 331 returnType='', 29 332 returnsBag=False): 333 ''' 334 @param functionName the name of this function as used by the factory 335 and any XACML policies 336 @param functionId an optional identifier that can be used by your 337 code for convenience 338 @param paramTypes the type of each parameter, in order, required by 339 this function, as used by the factory and any XACML 340 documents 341 @param paramIsBag whether or not each parameter is actually a bag 342 of values 343 @param returnType the type returned by this function, as used by 344 the factory and any XACML documents 345 @param returnsBag whether or not this function returns a bag of values 346 ''' 30 347 31 348 self.functionName = functionName … … 103 420 # TODO: Condition classes - minimal implementation until opportunity to fully 104 421 # implement 105 class Function(object):106 def __init__(self, *arg, **kw):107 raise NotImplementedError()108 109 @classmethod110 def getInstance(cls, root):111 raise NotImplementedError()112 113 422 class BagFunction(FunctionBase): 114 423 def __init__(self, *arg, **kw): … … 154 463 155 464 class MatchFunction(FunctionBase): 156 NAME_REGEXP_STRING_MATCH = \ 157 "urn:oasis:names:tc:xacml:1.0:function:regexp-string-match" 158 NAME_RFC822NAME_MATCH = \ 159 "urn:oasis:names:tc:xacml:1.0:function:rfc822Name-match" 160 NAME_X500NAME_MATCH = \ 161 "urn:oasis:names:tc:xacml:1.0:function:x500Name-match" 465 NAME_REGEXP_STRING_MATCH = FunctionBase.FUNCTION_NS + "regexp-string-match" 466 NAME_RFC822NAME_MATCH = FunctionBase.FUNCTION_NS + "rfc822Name-match" 467 NAME_X500NAME_MATCH = FunctionBase.FUNCTION_NS + "x500Name-match" 162 468 163 469 supportedIdentifiers = (NAME_REGEXP_STRING_MATCH, … … 192 498 class EqualFunction(FunctionBase): 193 499 supportedIdentifiers = ( 194 "urn:oasis:names:tc:xacml:1.0:function:anyURI-equal",195 "urn:oasis:names:tc:xacml:1.0:function:base64Binary-equal",196 "urn:oasis:names:tc:xacml:1.0:function:boolean-equal",197 "urn:oasis:names:tc:xacml:1.0:function:date-equal",198 "urn:oasis:names:tc:xacml:1.0:function:dateTime-equal",199 "urn:oasis:names:tc:xacml:1.0:function:dayTimeDuration-equal",200 "urn:oasis:names:tc:xacml:1.0:function:double-equal",201 "urn:oasis:names:tc:xacml:1.0:function:hexBinary-equal",202 "urn:oasis:names:tc:xacml:1.0:function:integer-equal",203 "urn:oasis:names:tc:xacml:1.0:function:rfc822Name-equal",204 "urn:oasis:names:tc:xacml:1.0:function:string-equal",205 "urn:oasis:names:tc:xacml:1.0:function:time-equal",206 "urn:oasis:names:tc:xacml:1.0:function:x500Name-equal",207 "urn:oasis:names:tc:xacml:1.0:function:yearMonthDuration-equal"500 FunctionBase.FUNCTION_NS + "anyURI-equal", 501 FunctionBase.FUNCTION_NS + "base64Binary-equal", 502 FunctionBase.FUNCTION_NS + "boolean-equal", 503 FunctionBase.FUNCTION_NS + "date-equal", 504 FunctionBase.FUNCTION_NS + "dateTime-equal", 505 FunctionBase.FUNCTION_NS + "dayTimeDuration-equal", 506 FunctionBase.FUNCTION_NS + "double-equal", 507 FunctionBase.FUNCTION_NS + "hexBinary-equal", 508 FunctionBase.FUNCTION_NS + "integer-equal", 509 FunctionBase.FUNCTION_NS + "rfc822Name-equal", 510 FunctionBase.FUNCTION_NS + "string-equal", 511 FunctionBase.FUNCTION_NS + "time-equal", 512 FunctionBase.FUNCTION_NS + "x500Name-equal", 513 FunctionBase.FUNCTION_NS + "yearMonthDuration-equal" 208 514 ) 209 515 … … 227 533 } 228 534 229 typeMap = {NAME_STRING_EQUAL: "http://www.w3.org/2001/XMLSchema#string"} 230 231 def __init__(self, functionName, **kw): 232 super(EqualFunction, self).__init__(functionName, **kw) 535 _attrClasses = ( 536 AnyURIAttribute, 537 Base64BinaryAttribute, 538 BooleanAttribute, 539 DateAttribute, 540 DateTimeAttribute, 541 DayTimeDurationEqual, 542 DoubleAttribute, 543 HexBinaryAttribute, 544 IntegerAttribute, 545 RFC822NameAttribute, 546 StringAttribute, 547 TimeAttribute, 548 X500NameAttribute, 549 YearMonthDurationAttribute 550 ) 551 552 typeMap = dict([(i, j.identifier) for i,j in zip(supportedIdentifiers, 553 _attrClasses)]) 554 555 def __init__(self, functionName, argumentType=None, **kw): 556 if kw.get('functionId') is None: 557 kw['functionId'] = 0 558 559 if kw.get('paramType') is None: 560 kw['paramType'] = EqualFunction._getArgumentType(functionName) 561 562 super(EqualFunction, self).__init__(functionName, **kw) 233 563 234 564 def evaluate(self, inputs, evaluationCtx): … … 252 582 return EvaluationResult(argValues[0] == argValues[1]) 253 583 254 def getArgumentType(functionName): 255 datatype = EqualFunction.typeMap.get(functionName); 256 if datatype is None: 257 raise AttributeError("Not a standard function: %s" % functionName) 584 @classmethod 585 def _getArgumentType(cls, functionName): 586 argumentType = cls.typeMap.get(functionName) 587 if argumentType is None: 588 if functionName in cls.supportedIdentifiers: 589 raise NotImplementedError('No implementation is currently ' 590 'available for "%s"' % functionName) 591 else: 592 raise TypeError("Not a standard function: %s" % functionName) 258 593 259 return datatype594 return argumentType 260 595 261 596 class AddFunction(FunctionBase): -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/signaturehandler/__init__.py
r5067 r5168 39 39 from ZSI.wstools.Namespaces import ENCRYPTION, WSU 40 40 from ZSI.wstools.Namespaces import OASIS as _OASIS 41 from ConfigParser import RawConfigParser 41 42 42 43 # Enable settings from a config file … … 225 226 self.cfg = cfgClass() 226 227 self.cfg.read(cfg) 227 else: 228 self.cfg.parse(section=cfgFileSection, prefix=cfgFilePrefix) 229 230 elif isinstance(cfg, RawConfigParser): 228 231 log.debug("BaseSignatureHandler.__init__: config object input ...") 229 232 self.cfg = cfgClass(cfg=cfg) 230 231 if cfg: # config object or config file path was set232 log.debug("BaseSignatureHandler.__init__: Processing config "233 "file...")234 233 self.cfg.parse(section=cfgFileSection, prefix=cfgFilePrefix) 234 235 elif isinstance(cfg, WSSecurityConfig): 236 log.debug("BaseSignatureHandler.__init__: WSSSecurityConfig " 237 "object input ...") 238 self.cfg = cfg 239 else: 240 raise TypeError("cfg keyword set to %s type. cfg must be a " 241 "file path string, RawConfigParser derived " 242 "class instance or WSSecurityConfig type" % 243 cfg.__class__) 235 244 236 245 # Also update config from keywords set -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/authz/__init__.py
r5157 r5168 15 15 from ndg.security.server.wsgi import NDGSecurityPathFilter 16 16 from ndg.security.common.X509 import X500DN 17 from ndg.security.common.authz.xacml import Request, Subject, Attribute, Policy 18 from ndg.security.common.authz.xacml import PDP as XacmlPDP 17 from ndg.security.common.authz.msi import Policy 19 18 from ndg.security.server.wsgi import NDGSecurityMiddlewareBase, \ 20 19 NDGSecurityMiddlewareConfigError 21 20 22 23 # TODO: move this class to separate resource constraint module24 class Resource(object):25 def __init__(self, uri, attributes=[]):26 self.uri = uri27 self.attributes = attributes28 29 def __eq__(self, uri):30 return self.uri == uri31 32 from ndg.security.common.authz.pdp import PDPInterface33 34 21 from ndg.security.server.wsgi import NDGSecurityMiddlewareBase, \ 35 22 NDGSecurityMiddlewareConfigError 36 23 37 class Action(object): 38 pass 39 40 class Environment(object): 41 pass 42 43 from elementtree import ElementTree as ET 44 45 class PDP(XacmlPDP): 46 def __init__(self, policyFilePath=None): 47 if policyFilePath: 48 elem = ET.parse(policyFilePath) 49 root = elem.getroot() 50 self.policy = Policy.getInstance(root) 51 else: 52 self.policy = Policy() 53 54 def evaluate(self, request): 55 '''Make access control decision''' 56 if action is None: 57 action = Action() 58 59 if environ is None: 60 environ = Environment() 61 62 #super(PDP, self).accessPermitted(subject, resource, action, environ) 63 for attr in resource.attributes: 64 if attr in subject.attributes: 65 return True 66 67 return False 68 69 70 class PDPMiddlewareConfigError(NDGSecurityMiddlewareConfigError): 71 '''Policy Decision Point Middleware Configuration error''' 24 from ndg.security.common.authz.msi import PDP, Request, Resource 25 from ndg.security.common.wssecurity import WSSecurityConfig 26 from ndg.security.common.sessionmanager import SessionManagerClient, \ 27 SessionNotFound, SessionCertTimeError, SessionExpired, InvalidSession, \ 28 AttributeRequestDenied 29 30 class SubjectRetrievalError(Exception): 31 """Generic exception class for errors related to information about the 32 subject""" 33 34 class InvalidAttributeCertificate(SubjectRetrievalError): 35 "The certificate containing authorisation roles is invalid" 36 def __init__(self, msg=None): 37 SubjectRetrievalError.__init__(self, msg or 38 InvalidAttributeCertificate.__doc__) 39 40 class SessionExpiredMsg(SubjectRetrievalError): 41 'Session has expired. Please re-login' 42 def __init__(self, msg=None): 43 SubjectRetrievalError.__init__(self, msg or SessionExpiredMsg.__doc__) 44 45 class InvalidSessionMsg(SubjectRetrievalError): 46 'Session is invalid. Please try re-login' 47 def __init__(self, msg=None): 48 SubjectRetrievalError.__init__(self, msg or 49 InvalidSessionMsg.__doc__) 50 51 class InitSessionCtxError(SubjectRetrievalError): 52 'A problem occurred initialising a session connection' 53 def __init__(self, msg=None): 54 SubjectRetrievalError.__init__(self, msg or 55 InitSessionCtxError.__doc__) 56 57 class AttributeCertificateRequestError(SubjectRetrievalError): 58 'A problem occurred requesting a certificate containing authorisation roles' 59 def __init__(self, msg=None): 60 SubjectRetrievalError.__init__(self,msg or 61 AttributeCertificateRequestError.__doc__) 72 62 73 63 class PEPMiddleware(NDGSecurityPathFilter): … … 86 76 def __init__(self, app, global_conf, prefix='', **app_conf): 87 77 88 pdpCfg = {} 89 pdpCfgPfx = prefix + 'pdp.' 90 pdpCfgLen = len(pdpCfgPfx) 91 for k,v in app_conf.items(): 92 if k.startswith(pdpCfgPfx): 93 pdpCfg[k[pdpCfgLen:]] = app_conf.pop(k) 78 pdpCfg = PEPMiddleware._filterKeywords(app_conf, 'pdp.') 79 self.pdp = PDP(**pdpCfg) 80 81 self.wssecurityCfg = WSSecurityConfig() 82 wssePrefix = 'sessionManagerClient.wssecurity' 83 self.wssecurityCfg.update(app_conf, prefix=wssePrefix) 84 85 PEPMiddleware._filterKeywords(app_conf, wssePrefix+'.') 94 86 95 self.pdp = PDP(**pdpCfg) 96 97 super(PEPMiddleware, self).__init__(app, 98 global_conf, 99 prefix=prefix, 87 self.sslCACertFilePathList = app_conf.pop( 88 'sessionManagerClient.sslCACertFilePathList', []) 89 90 super(PEPMiddleware, self).__init__(app, 91 global_conf, 92 prefix=prefix, 100 93 **app_conf) 101 102 94 95 @staticmethod 96 def _filterKeywords(conf, prefix): 97 filteredConf = {} 98 prefixLen = len(prefix) 99 for k, v in conf.items(): 100 if k.startswith(prefix): 101 filteredConf[k[prefixLen:]] = conf.pop(k) 102 103 return filteredConf 104 103 105 @NDGSecurityPathFilter.initCall 104 106 def __call__(self, environ, start_response): 107 self.session = self.environ.get(self.sessionKey) 105 108 if self.isAuthenticated: 106 109 if self.isAuthorized(): … … 111 114 else: 112 115 response = "Not authenticated" 113 start_response(PEPMiddleware.getStatusMessage(401), 116 start_response(PEPMiddleware.getStatusMessage(401), 114 117 [('Content-type', 'text/plain') , 115 118 ('Content-length', str(len(response)))]) 116 119 return response 120 121 def _getAttributeCertificate(self, attributeAuthorityURI): 122 try: 123 # Create Session Manager client - if a file path was set, setting 124 # are read from a separate config file section otherwise, from the 125 # PDP config object 126 smClnt = SessionManagerClient( 127 uri=self.session['sessionManagerURI'], 128 sslCACertFilePathList=self.sslCACertFilePathList, 129 cfg=self.wssecurityCfg) 130 except Exception, e: 131 log.error("Creating Session Manager client: %s" % e) 132 raise InitSessionCtxError() 133 134 135 try: 136 # Make request for attribute certificate 137 attCert = smClnt.getAttCert( 138 attributeAuthorityURI=attributeAuthorityURI, 139 sessID=self.session['sessionID']) 140 return attCert 141 142 except AttributeRequestDenied, e: 143 log.error("Request for attribute certificate denied: %s" % e) 144 raise PDPUserAccessDenied() 145 146 except SessionNotFound, e: 147 log.error("No session found: %s" % e) 148 raise PDPUserNotLoggedIn() 149 150 except SessionExpired, e: 151 log.error("Session expired: %s" % e) 152 raise InvalidSessionMsg() 153 154 except SessionCertTimeError, e: 155 log.error("Session cert. time error: %s" % e) 156 raise InvalidSessionMsg() 117 157 158 except InvalidSession, e: 159 log.error("Invalid user session: %s" % e) 160 raise InvalidSessionMsg() 161 162 except Exception, e: 163 log.error("Request from Session Manager [%s] to Attribute " 164 "Authority [%s] for attribute certificate: %s: %s" % 165 (self.session['sessionManagerURI'], 166 attributeAuthorityURI, 167 e.__class__, e)) 168 raise AttributeCertificateRequestError() 169 170 118 171 def isAuthorized(self): 119 172 '''Check constraints on the requested URI and return boolean - access … … 121 174 environ = self.environ 122 175 123 # TODO: Refactor here perhaps calling resource constraint look-up or do 124 # inside PDP call? 125 resource = self.environ.get('ndg.security.server.wsgi.pep.resource') or \ 126 Resource(self.pathInfo) 127 128 session = self.environ[self.sessionKey] 129 user = Attribute(id='userId', value=session['username']) 130 sessionManager = Attribute(id='sessionManagerURI', 131 value=session['sessionManagerURI']) 132 role = Attribute(id='role', value='someAttribute') 133 subject = Subject(attributes={user.id: user, 134 sessionManager.id: sessionManager, 135 role.id: role}) 136 request = Request(subject, resource, environment=self.environ) 176 # Make a request object to pass to the PDP 177 request = Request() 178 request.subject.attributes['userId'] = self.session['username'] 179 request.resource = self.environ.get( 180 'ndg.security.server.wsgi.pep.resource') or Resource(self.pathInfo) 181 182 # Look for matching targets to the given resource 183 matchingTargets = [target for target in self.pdp.policy.targets 184 if target.regEx.match(request.resource.uri) \ 185 is not None] 186 187 attributeAuthorityURIs = [] 188 for matchingTarget in matchingTargets: 189 190 # Make call to relevant Attribute Authority if not already 191 # requested 192 if matchingTarget.attributeAuthorityURI not in \ 193 attributeAuthorityURIs: 194 attributeCertificate = self._getAttributeCertificate( 195 matchingTarget.attributeAuthorityURI) 196 attributeAuthorityURIs.append( 197 matchingTarget.attributeAuthorityURI) 198 199 request.subject.attributes.update( 200 {'roles': attributeCertificate.roles}) 201 137 202 response = self.pdp.evaluate(request) 138 203 return status … … 143 208 response''' 144 209 response = "Access Denied" 145 start_response(PEPMiddleware.getStatusMessage(403), 210 start_response(PEPMiddleware.getStatusMessage(403), 146 211 [('Content-type', 'text/plain') , 147 212 ('Content-length', str(len(response)))]) … … 156 221 "%r", status, headers) 157 222 158 if status.startswith(cls.triggerStatus) or environ['PATH_INFO'] =='/test_securedURI':159 environ['ndg.security.server.wsgi.pep.resource'] = Resource(environ['PATH_INFO'], attributes=['someAttribute'])223 if status.startswith(cls.triggerStatus) or environ['PATH_INFO'] == '/test_securedURI': 224 # environ['ndg.security.server.wsgi.pep.resource'] = Resource(environ['PATH_INFO']) 160 225 log.debug("PEPMiddleware.checker returning True") 161 226 return True … … 177 242 app = MultiHandler(app) 178 243 179 app.add_method(PEPMiddleware.id, 180 PEPMiddleware.filter_app_factory, 244 app.add_method(PEPMiddleware.id, 245 PEPMiddleware.filter_app_factory, 181 246 global_conf, 182 247 prefix=prefix, … … 186 251 187 252 188 super(AuthorizationMiddleware, self).__init__(app, 189 global_conf, 190 prefix=prefix, 253 super(AuthorizationMiddleware, self).__init__(app, 254 global_conf, 255 prefix=prefix, 191 256 **app_conf) 192 257 -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/openid/provider/__init__.py
r5148 r5168 84 84 errorMsg = "AuthNInterface configuration error" 85 85 86 class AuthNInterfaceCtx(object): 87 """Implement a derived version of this class to enable passing of any 88 login context information returned from AbstractAuthNInterface.login 89 to AbstractAuthNInterface.logout""" 90 86 91 class AbstractAuthNInterface(object): 87 92 '''OpenID Provider abstract base class for authentication configuration. … … 133 138 @raise AuthNInterfaceError: generic exception not described by the 134 139 other specific exception types. 140 @rtype: AuthNInterfaceCtx 141 @return: authentication context object for use by OpenID Provider to 142 handle logout. Pass any information required by the logout method via 143 this object. The object should be instance of a class derived from 144 AuthNInterfaceCtx 135 145 """ 136 146 raise NotImplementedError() … … 164 174 raise NotImplementedError() 165 175 176 def logout(self, authNInterfaceCtx): 177 """Stub to enable custom actions for logout. 178 179 @type authNInterfaceCtx: AuthNInterfaceCtx 180 @param authNInterfaceCtx: authentication context object returned from 181 login method 182 """ 183 raise NotImplementedError() 184 166 185 167 186 from ndg.security.server.wsgi.openid.provider.axinterface import \ … … 316 335 raise 317 336 337 # Authentication context object - set to a default. Authentication 338 # interface object should return a context object into this variable 339 # from its login method for the logout method to reference when it is 340 # later invoked. 341 self.authNInterfaceCtx = AuthNInterfaceCtx() 342 318 343 # Paths relative to base URL - Nb. remove trailing '/' 319 344 self.paths = dict([(k, opt[k].rstrip('/')) … … 825 850 # Invoke custom authentication interface plugin 826 851 try: 827 self. _authN.logon(environ,828 userIdentifier,829 self.query['username'],830 self.query.get('password', ''))852 self.authNInterfaceCtx = self._authN.logon(environ, 853 userIdentifier, 854 self.query['username'], 855 self.query.get('password', '')) 831 856 832 857 except AuthNInterfaceError, e: … … 858 883 self.session.pop('approved', None) 859 884 self.session.save() 885 886 try: 887 self._authN.logout(self.authNInterfaceCtx) 888 889 except Exception, e: 890 log.error("Unexpected exception raised during " 891 "logout: %s" % e) 892 msg = ("An internal error during logout. If the " 893 "problem persists contact your system " 894 "administrator.") 895 896 response = self._render.errorPage(environ, start_response, 897 msg) 898 return response 899 860 900 861 901 return self._redirect(start_response, self.query['success_to']) … … 1049 1089 # possibly via FetchRequest.getRequiredAttrs() 1050 1090 try: 1051 self.axResponse(ax_req, ax_resp, self. session.get('username'))1091 self.axResponse(ax_req, ax_resp, self.authNInterfaceCtx) 1052 1092 1053 1093 except OpenIDProviderMissingRequiredAXAttrs, e: -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/openid/provider/authninterface/sessionmanager.py
r5087 r5168 20 20 from ndg.security.server.wsgi.openid.provider import AbstractAuthNInterface, \ 21 21 AuthNInterfaceConfigError, AuthNInterfaceInvalidCredentials, \ 22 AuthNInterfaceUsername2IdentifierMismatch 22 AuthNInterfaceUsername2IdentifierMismatch, AuthNInterfaceCtx 23 23 24 24 from ndg.security.server.wsgi.utils.sessionmanagerclient import \ 25 25 WSGISessionManagerClient, AuthNServiceInvalidCredentials 26 26 27 27 28 class SessionManagerAuthNCtx(AuthNInterfaceCtx): 29 """Authentication Context class for passing session Id and Session Manager 30 URI to logout method AXResponse instance 31 """ 32 def __init__(self, uri=None, environKeyName=None, sessionId=None): 33 self.uri = uri 34 self.environKeyName = environKeyName 35 self.sessionId = sessionId 36 28 37 class SessionManagerOpenIDAuthNInterface(AbstractAuthNInterface): 29 38 '''Authentication interface class for OpenIDProviderMiddleware to enable … … 106 115 107 116 try: 117 authNCtx = SessionManagerAuthNCtx(uri=self._client.uri, 118 environKeyName=self._client._environKey) 108 119 self._client.environ = environ 109 self._client.connect(username, passphrase=password) 120 authNCtx.sessionId = self._client.connect(username, 121 passphrase=password)[-1] 110 122 111 123 except AuthNServiceInvalidCredentials, e: 112 124 log.exception(e) 113 125 raise AuthNInterfaceInvalidCredentials() 126 127 return authNCtx 114 128 115 129 … … 159 173 160 174 return userIdentifiers 175 176 def logout(self, authNCtx): 177 """ 178 @type authNCtx: SessionManagerAuthNCtx 179 @param authNCtx: authentication context object returned from 180 login method 181 """ 182 if not isinstance(authNCtx, SessionManagerAuthNCtx): 183 log.error("Expecting SessionManagerAuthNCtx type for authNCtx; " 184 "got: %s" % authNCtx.__class__.__name__) 185 raise AuthNInterfaceConfigError("Expecting SessionManagerAuthNCtx " 186 "type for authNCtx; got: %s" % 187 authNCtx.__class__.__name__) 188 189 try: 190 self._client.environ = environ 191 self._client.disconnect(sessID=authNCtx.sessionId) 192 193 except Exception, e: 194 log.exception(e) 195 raise AuthNInterfaceInvalidCredentials() -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/openid/provider/axinterface/__init__.py
r5148 r5168 36 36 raise NotImplementedError() 37 37 38 def __call__(self, ax_req, ax_resp, userID):38 def __call__(self, ax_req, ax_resp, authNInterfaceCtx): 39 39 """Add the attributes to the ax_resp object requested in the ax_req 40 40 object. If it is not possible to return them, raise … … 48 48 @param ax_resp: attribute exchange response object. This method should 49 49 update the settings in this object. Use addValue and setValues methods 50 @type userID: basestring 51 @param userID: user's local ID 50 @type authNInterfaceCtx: AuthNInterfaceCtx 51 @param authNInterfaceCtx: custom authentication context information set 52 at login. See ndg.security.server.openid.provider.AuthNInterfaceCtx 53 for more information 52 54 """ 53 55 raise NotImplementedError() -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/openid/provider/axinterface/sessionmanager.py
r5148 r5168 31 31 endpoint''' 32 32 33 propertyNames = ('sessionManagerURI', 'sessionManagerURITypeURI') 33 propertyNames = ( 34 'sessionManagerURI', 35 'sessionManagerURITypeURI', 36 'sessionId', 37 'sessionIdTypeURI') 34 38 35 39 def __init__(self, **cfg): … … 48 52 setattr(self, name, val) 49 53 50 def __call__(self, ax_req, ax_resp, userID):54 def __call__(self, ax_req, ax_resp, authNInterfaceCtx): 51 55 """Add the attributes to the ax_resp object requested in the ax_req 52 56 object. If it is not possible to return them, raise … … 60 64 @param ax_resp: attribute exchange response object. This method should 61 65 update the settings in this object. Use addValue and setValues methods 62 @type userID: basestring 63 @param userID: user's local ID 66 @type authNInterfaceCtx: AuthNInterfaceCtx 67 @param authNInterfaceCtx: custom authentication context information set 68 at login. See ndg.security.server.openid.provider.AuthNInterfaceCtx 69 for more information 64 70 """ 65 71 reqAttrURIs = ax_req.getRequiredAttrs() … … 67 73 ax_resp.addValue(self.sessionManagerURITypeURI, 68 74 self.sessionManagerURI) 75 76 if self.sessionIdTypeURI in reqAttrURIs: 77 if not isinstance(authNInterfaceCtx, AuthNInterfaceCtx): 78 raise AXInterfaceConfigError("Expecting AuthNInterfaceCtx " 79 "type for authNInterfaceCtx arg; " 80 "got: %s" % 81 authNInterfaceCtx.__class__.__name__) 82 83 ax_resp.addValue(self.sessionIdTypeURI,authNInterfaceCtx.sessionId) -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/integration/authz/securedapp.ini
r5165 r5168 42 42 paste.filter_app_factory=ndg.security.server.wsgi.authz:AuthorizationMiddleware.filter_app_factory 43 43 prefix = authz. 44 authz.pdp.policyFilePath = %(here)s/policy.xml 45 #authz.pep.pathMatchList = /test_securedURI 44 pdp.policyFilePath = %(here)s/policy.xml 46 45 47 #[filter:PDPMiddlewareFilter] 48 ##paste.filter_app_factory=ndg.security.server.wsgi.pdp:PDPMiddleware.filter_app_factory 49 ##prefix = pdp. 50 ##paste.filter_app_factory = ndg.security.server.wsgi.pdp:PDPMiddlewareAppFactory 51 #paste.filter_app_factory = ndg.security.server.wsgi.pdp:PDPHandlerMiddleware.filter_app_factory 46 # Settings for connection to the user's Session Manager 47 sessionManagerClient.sslCACertFilePathList= 48 # 49 # WS-Security Settings for call to Session Manager 50 51 # Signature of an outbound message 52 53 # Certificate associated with private key used to sign a message. The sign 54 # method will add this to the BinarySecurityToken element of the WSSE header. 55 # binSecTokValType attribute must be set to 'X509' or 'X509v3' ValueType. 56 # As an alternative, use signingCertChain - see below... 57 58 # PEM encode cert 59 sessionManagerClient.wssecurity.signingCertFilePath= 60 61 # PEM encoded private key file 62 sessionManagerClient.wssecurity.signingPriKeyFilePath= 63 64 # Password protecting private key. Leave blank if there is no password. 65 sessionManagerClient.wssecurity.signingPriKeyPwd= 66 67 # Provide a space separated list of file paths 68 sessionManagerClient.wssecurity.caCertFilePathList= 69 70 # ValueType for the BinarySecurityToken added to the WSSE header 71 sessionManagerClient.wssecurity.reqBinSecTokValType=X509v3 72 73 # Add a timestamp element to an outbound message 74 sessionManagerClient.wssecurity.addTimestamp=True -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/integration/authz/securityservices.ini
r5154 r5168 24 24 sessionManagerPath = /SessionManager 25 25 sessionManagerURI = %(baseURI)s%(sessionManagerPath)s 26 openid.ax.sessionManagerURI.typeURI=urn:ndg.security.openid.sessionManagerURI 26 openid.ax.sessionManagerURI.typeURI=urn:ndg:security:openid:sessionManagerURI 27 openid.ax.sessionId.typeURI=urn:ndg:security:openid:sessionId 27 28 28 29 #______________________________________________________________________________ … … 239 240 authkit.openid.ax.alias.sessionManagerURI=sessionManagerURI 240 241 242 authkit.openid.ax.typeuri.sessionId=%(openid.ax.sessionId.typeURI)s 243 authkit.openid.ax.required.sessionId=True 244 authkit.openid.ax.alias.sessionId=sessionId 245 241 246 # Template for signin 242 247 #authkit.openid.template.obj = … … 292 297 293 298 294 #openid.provider.sregResponseHandler=ndg.security.server.pylons.container.lib.openid_provider_util:esgSRegResponseHandler295 299 openid.provider.axResponse.class=ndg.security.server.wsgi.openid.provider.axinterface.sessionmanager.SessionManagerAXInterface 296 300 openid.provider.axResponse.sessionManagerURI=%(sessionManagerURI)s 297 301 openid.provider.axResponse.sessionManagerURITypeURI=%(openid.ax.sessionManagerURI.typeURI)s 302 openid.provider.axResponse.sessionManagerURI=%(sessionId)s 303 openid.provider.axResponse.sessionIdTypeURI=%(openid.ax.sessionId.typeURI)s 298 304 299 305 # Basic Authentication interface to demonstrate capabilities
Note: See TracChangeset
for help on using the changeset viewer.