[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]
Subject: A suggestion for better handling of multi-valued attributes in conditions
XACML allows attributes to be multi-valued but is rather poor at handling non-trivial comparisons of multi-valued attributes. Suppose I have resources with a multi-valued integer "code" attribute and I want to write an expression that is true if and only if at least one of the code values is in the range 100 to 200. A naive solution would look like this: <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:and"> <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:any-of"> <Function FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal"/> <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="http://example.com/code" DataType="http://www.w3.org/2001/XMLSchema#integer" MustBePresent="false"/> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#integer" >100</AttributeValue> </Apply> <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:any-of"> <Function FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal"/> <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="http://example.com/code" DataType="http://www.w3.org/2001/XMLSchema#integer" MustBePresent="false"/> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#integer" >200</AttributeValue> </Apply> </Apply> However, this doesn't work as desired. Suppose that a particular resource has the code values 50 and 250. The expression would evaluate to true for this resource, though it doesn't have a code value between 100 and 200, because there is no correlation between the value that satisfies the first part of the "and" and the value that satisfies the second part of the "and". In this case, both parts are satisfied, but by different values. Unfortunately, XACML doesn't provide a way to enforce such a correlation, which is why it is poor at handling comparisons of multi-valued attributes. When iterating through an attribute's values (with something like the any-of function) it is only possible to apply a function to each value, but what is needed for a case like the example above is the capability to apply an arbitrary expression to each value in turn. This suggests binding the values to a variable that can be referenced throughout the desired expression. There are a number of ways XACML could be extended to provide such a capability, but the neatest I've found is to extend ExpressionType like so: <xs:element name="ForAny" type="xacml:IterativeExpressionType" substitutionGroup="xacml:Expression"/> <xs:element name="ForAll" type="xacml:IterativeExpressionType" substitutionGroup="xacml:Expression"/> <xs:complexType name="IterativeExpressionType"> <xs:complexContent> <xs:extension base="xacml:ExpressionType"> <xs:sequence> <xs:element ref="xacml:Expression"/> <!-- Must be a bag. --> <xs:element ref="xacml:Expression"/> </xs:sequence> <xs:attribute name="VariableId" type="xs:string" use="required"/> </xs:extension> </xs:complexContent> </xs:complexType> The IterativeExpressionType contains two expressions. The first expression must evaluate to a bag. The VariableId XML attribute names the variable that will iterate over the values of this bag. The variable's data-type is the same as the primitive data-type of the members of the bag. The second expression is an arbitrary expression that evaluates to a Boolean value. The second expression would normally contain one or more references to the named variable. A ForAny expression is evaluated by repeatedly evaluating the second expression with the variable bound to each value of the bag in turn. The overall Boolean result of the ForAny expression is obtained by combining the results of evaluating the second expression according to the "or" function. The ForAll expression is evaluated in the same way except that the results of evaluating the second expression are combined according to the "and" function. Using the ForAny expression it is now possible to write an expression that evaluates to true if and only if the code attribute has at least one value in the range 100 to 200: <ForAny VariableId="code"> <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="http://example.com/code" DataType="http://www.w3.org/2001/XMLSchema#integer" MustBePresent="false"/> <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:and"> <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal"> <VariableReference VariableId="code"/> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#integer" >100</AttributeValue> </Apply> <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal"> <VariableReference VariableId="code"/> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#integer" >200</AttributeValue> </Apply> </Apply> </ForAny> Now, some value of the code attribute has to satisfy both parts of the "and" for the overall expression to evaluate to true. Although I was only trying to find a way to sensibly handle multi-valued attributes, I have hit upon a generalization for the bag handling functions. For example, this expression using the any-of-any function: <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:any-of-any"> <Function FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal"/> <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag"> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string" >Ringo</AttributeValue> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string" >Mary</AttributeValue> </Apply> <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag"> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string" >John</AttributeValue> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string" >Paul</AttributeValue> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string" >George</AttributeValue> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string" >Ringo</AttributeValue> </Apply> </Apply> can also be expressed with ForAny: <ForAny VariableId="somebody"> <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag"> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string" >Ringo</AttributeValue> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string" >Mary</AttributeValue> </Apply> <ForAny VariableId="beatle"> <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag"> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string" >John</AttributeValue> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string" >Paul</AttributeValue> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string" >George</AttributeValue> <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string" >Ringo</AttributeValue> </Apply> <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> <VariableReference VariableId="somebody"/> <VariableReference VariableId="beatle"/> </Apply> </ForAny> </ForAny> In fact, all of these functions have an equivalent representation using ForAny and/or ForAll: time-in-range type-is-in type-at-least-one-member-of type-subset type-set-equals any-of all-of any-of-any all-of-any any-of-all all-of-all The advantage of the ForAny and ForAll expressions is that they can also apply an arbitrarily complex expression to the members of a bag whereas the higher-order bag functions can only apply a function. In a previous email I indicated four reasonable combinations of any-of and all-of for a higher-order bag function of two bag arguments, though only two such functions have been defined: (1) x_of_x f [] ys = True x_of_x f (x:xs) ys = (any_of f x ys) && (x_of_x f xs ys) (2) x_of_x f xs [] = False x_of_x f xs (y:ys) = (all_of f xs y) || (x_of_x f xs ys) (3) x_of_x f xs [] = True x_of_x f xs (y:ys) = (any_of f xs y) && (x_of_x f xs ys) (4) x_of_x f [] ys = False x_of_x f (x:xs) ys = (all_of f x ys) || (x_of_x f xs ys) Each of these combinations can be expressed using ForAny and ForAll, which would remove any need to define the two missing functions. (1) <ForAll VariableId="x"> ... an expression evaluating to a bag of the primitive data-type of the first argument of function "f" <ForAny VariableId="y"> ... an expression evaluating to a bag of the primitive data-type of the second argument of function "f" <Apply FunctionId="f"> <VariableReference VariableId="x"/> <VariableReference VariableId="y"/> </Apply> </ForAny> </ForAll> (2) <ForAny VariableId="y"> ... an expression evaluating to a bag of the primitive data-type of the second argument of function "f" <ForAll VariableId="x"> ... an expression evaluating to a bag of the primitive data-type of the first argument of function "f" <Apply FunctionId="f"> <VariableReference VariableId="x"/> <VariableReference VariableId="y"/> </Apply> </ForAll> </ForAny> (3) <ForAll VariableId="y"> ... an expression evaluating to a bag of the primitive data-type of the second argument of function "f" <ForAny VariableId="x"> ... an expression evaluating to a bag of the primitive data-type of the first argument of function "f" <Apply FunctionId="f"> <VariableReference VariableId="x"/> <VariableReference VariableId="y"/> </Apply> </ForAny> </ForAll> (4) <ForAny VariableId="x"> ... an expression evaluating to a bag of the primitive data-type of the first argument of function "f" <ForAll VariableId="y"> ... an expression evaluating to a bag of the primitive data-type of the second argument of function "f" <Apply FunctionId="f"> <VariableReference VariableId="x"/> <VariableReference VariableId="y"/> </Apply> </ForAll> </ForAny> The map function could also be generalized to allow an arbitrary expression to transform a bag of values, instead of just a function: <xs:element name="Map" type="xacml:IterativeExpressionType" substitutionGroup="xacml:Expression"/> In this case the second contained expression is an arbitrary expression that evaluates to some primitive data-type. A Map expression is evaluated by repeatedly evaluating the second expression with the variable bound to each value of the bag from the first contained expression. The overall result of the Map expression is a bag containing the results of evaluating the second expression. There you have it - a suggestion for extending and generalizing XACML to properly handle non-trivial comparisons of multi-valued attributes. Regards, Steven
[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]