Skip to content

Enable policy writers to define and reuse composite functions in order to simplify Apply expressions across policies #34

@cdanger

Description

@cdanger

#22 and #23 showed the need to add new XACML functions in order to simplify very common Apply expressions that compose (math sense) two or more existing functions together.

For example, in #23 , the proposed empty-bag (resp. non-empty-bag) function is a composition of bag-size andinteger-equal(resp. integer-greater-than) functions.

So instead of adding such functions to the XACML spec every time we need a new one, they could be defined by the policy writers themselves in XACML at a global level (like #12 ?) so that they can be reused in Apply expressions, furthermore shared with other policy writers, and even further with the whole XACML community, on the TC's github for instance, as community extensions to the standard.

So we need a syntax to define new functions based on function composition, i.e. calling other functions:

<xs:element name="FunctionDefinition" type="FunctionDefinitionType">
  <!--  A VariableReference used in a Function's definition must refer to one of the function's variables. -->
  <xs:key name="FunctionVariableKey"  >  
    <xs:selector xpath="Variable" />  
    <xs:field xpath="@Id" />  
  </xs:key>  
  <xs:keyref name="FunctionVariableKeyRef" refer="FunctionVariableKey">  
    <xs:selector xpath="//VariableReference" />  
    <xs:field xpath="@VariableId" />  
  </xs:keyref>  
</xs:element>

<xs:complexType name="FunctionDefinitionType">
  <xs:complexContent>
      <xs:sequence>
        <!-- Function variables-->
        <xs:element name="Variable" type="xs:ID" minOccurs="1" maxOccurs="unbounded" />
        <!-- Function expression, i.e. call to another function with certain arguments -->
        <xs:element ref="xacml:ApplyExpression"/>
      </xs:sequence>
      <xs:attribute name="FunctionId" type="xs:anyURI" use="required"/>
  </xs:complexContent>
</xs:complexType>

<xs:element name="ApplyExpression" type="ApplyExpressionType" />
<!-- Similar to Apply but as it is in a Function Definition that must be context-independant, i.e. not depending on request context, AttributeDesignators/AttributeSelectors are not allowed as arguments here, i.e. only VariableReferences to the Function's VariablesAttributeValues, AttributeValues, <Function>s,  and ApplyExpressions (recursive)  -->
<xs:complexType name="ApplyExpressionType">
  <xs:complexContent>
    <xs:choice minOccurs="1" maxOccurs="unbounded">
          <!-- Reference to one of the Function Variables (defined in the FunctionDefinition)-->
          <xs:element ref="xacml:VariableReference"/>
          <xs:element ref="xacml:AttributeValue"/>
          <xs:element ref="xacml:Function"/>
          <xs:element ref="xacml:ApplyExpression"/>
     </xs:choice>
    <xs:attribute name="FunctionId" type="xs:anyURI" use="required"/>
  </xs:complexContent>
</xs:complexType>

Some examples based on #22 and #23 (defining empty-bag, not-empty-bag, integer-average functions):

<FunctionDefinition FunctionId="urn:oasis:names:tc:xacml:3.0:function:empty-bag">
  <Variable>bag</Variable>
  <ApplyExpression FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-equal">
    <ApplyExpression FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag-size">
      <VariableReference VariableId="bag" />
    </ApplyExpression>
    <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#integer">0</AttributeValue>
  </ApplyExpression>
</FunctionDefinition>

<FunctionDefinition FunctionId="urn:oasis:names:tc:xacml:3.0:function:not-empty-bag">
  <Variable>bag</Variable>
  <ApplyExpression FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-greater-than">
    <ApplyExpression FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag-size">
      <VariableReference VariableId="bag" />
    </ApplyExpression>
    <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#integer">0</AttributeValue>
  </ApplyExpression>
</FunctionDefinition>

Now you can do:

<Apply FunctionId="urn:oasis:names:tc:xacml:3.0:function:empty-bag">
  <AttributeDesignator
              Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
              AttributeId="http://example.com/some-attribute"
              DataType="http://www.w3.org/2001/XMLSchema#string"  MustBePresent="false"/>
 </Apply>

 <Apply FunctionId="urn:oasis:names:tc:xacml:3.0:function:non-empty-bag">
  <AttributeDesignator
              Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
              AttributeId="http://example.com/some-attribute"
              DataType="http://www.w3.org/2001/XMLSchema#string"  MustBePresent="false"/>
</Apply>

TODO:

  1. Define a standard package format or parent XML element for wrapping such <FunctionDefinition>s, maybe the same as GlobalVariableDefinitions (Add global variable definitions #12).

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions