OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

xacml-comment message

[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]