oasis-tcs / xacml-spec

OASIS XACML TC: List for tracking issues and features for the OASIS XACML TC. https://github.com/oasis-tcs/xacml-spec
Other
4 stars 0 forks source link

Simplify policy and policy set references and versioning #16

Open steven-legg opened 6 months ago

steven-legg commented 6 months ago

References to policies and policy sets (from within policies and policy sets) are instances of the following type:

    <xs:complexType name="IdReferenceType">
        <xs:simpleContent>
            <xs:extension base="xs:anyURI">
                <xs:attribute name="Version" type="xacml:VersionMatchType" use="optional"/>
                <xs:attribute name="EarliestVersion" type="xacml:VersionMatchType" use="optional"/>
                <xs:attribute name="LatestVersion" type="xacml:VersionMatchType" use="optional"/>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>

The implementation experience of the active members of the TC is that the EarliestVersion and LatestVersion attributes never get used, nor does the pattern matching ability of the Version attribute.

Policies and policy sets have a Version attribute that, although used, carries information that could just as easily be encoded (and probably should be encoded) into the URI.

The proposed change is to remove the Version attribute from Policy and PolicySet and to replace IdReferenceType with xs:anyURI.

This leads to the definitions:

    <xs:element name="PolicySetIdReference" type="xs:anyURI"/>
    <xs:element name="PolicyIdReference" type="xs:anyURI"/>
    <xs:element name="GlobalVariableIdReference" type="xs:anyURI"/> <!-- #12 -->

The names, though, suggest that we are referencing an identifier rather than the identified object. These names make more sense (and distinguish the simplified references from the more complicated form in XACML 3.0):

    <xs:element name="PolicySetReference" type="xs:anyURI"/>
    <xs:element name="PolicyReference" type="xs:anyURI"/>
    <xs:element name="GlobalVariableReference" type="xs:anyURI"/>

However, note that #12 suggests GlobalVariableReference as a possible new kind of expression.

We could go over to referencing policies and global variables by XML attribute instead of by element content (to align with simpler XSD in #12), which suggests:

    <xs:element name="PolicyIdReference">
        <xs:attribute name="PolicyId" type="xs:anyURI"/>
    </xs:element>

    <xs:element name="GlobalVariableIdReference">
        <xs:attribute name="GlobalVariableId" type="xs:anyURI"/>
    </xs:element>

It would be less verbose in XML but more verbose in JSON:

As element content:

<xacml:PolicyIdReference>http://example.com/mypolicy</xacml:PolicyIdReference>

{
    "PolicyIdReference": "http://example.com/mypolicy"
}

As attributes:

<xacml:PolicyIdReference PolicyId="http://example.com/mypolicy"/>

{
    "PolicyIdReference": { "PolicyId": "http://example.com/mypolicy" }
}
cdanger commented 6 months ago

The names, though, suggest that we are referencing an identifier rather than the identified object. These names make more sense (and distinguish the simplified references from the more complicated form in XACML 3.0):

    <xs:element name="PolicySetReference" type="xs:anyURI"/>
    <xs:element name="PolicyReference" type="xs:anyURI"/>
    <xs:element name="GlobalVariableReference" type="xs:anyURI"/>

However, note that #12 suggests GlobalVariableReference as a possible new kind of expression.

Some comments:

  1. Indeed, issue #12 suggests that GlobalVariableReference be a new kind of Expression (much like VariableReferences), unlike Policy(Set)References, so I'd rather not mix the discussions on both types of references in this issue. I suggest we leave the definition of GlobalVariableReference to #12 only.

  2. In #11, we decided to get rid of PolicySet and have a new Policy definition replace both former Policy/PolicySet, so no need for PolicySetReference anymore. PolicyReference covers both.

  3. In #9 we introduced parameterized policies, and we're discussing references to such policies, so I am thinking since we are re-defining policy references here, we can use the new PolicyReference type definition to reference parameterized ones as well, and therefore avoid defining a new type like ParameterizedPolicyReference (which increases schema complexity). A parameterized policy reference is just a policy reference with arguments, so I suggest to take @steven-legg 's proposal to reference by XML attribute, and add the optional Expressions for the policy arguments if there is any, i.e. if the policy is parameterized:

<xs:element name="PolicyReference" type="PolicyReferenceType"/>
<xs:complexType name="PolicyReferenceType">
        <xs:sequence>
            <xs:element ref="xacml:Expression"  minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
     <xs:attribute name="PolicyId" type="xs:anyURI"/>
</xs:complexType>

So a reference to a non- parameterized policy would look like @steven-legg 's example before, although I can't see why still we have to call it PolicyIdReference instead of PolicyReference:

<PolicyReference PolicyId="http://example.com/mypolicy"/>

And a reference to a parameterized policy with 2 parameters for instance like this:

<PolicyReference PolicyId="http://example.com/mypolicy2">
  <GlobalVariableReference GlobalVariableId="X"/>
  <VariableReference VariableId="y"/>
</PolicyReference>
steven-legg commented 5 months ago

A potential objection to having a single policy reference type with optional arguments is that the parameters for parameterized policies can have default values so the arguments can be left out. A policy reference with no arguments could be a reference to a regular policy or it could be a reference to a parameterized policy using the default values. It isn't obvious what one is looking at without fetching the referenced policy.

A counter argument is that people shouldn't be dealing with the raw XML/JSON/YAML and should use better PAPs that do the looking for them.

steven-legg commented 5 months ago

PolicyIdReference is currently used in three places: the children of PolicySet (earmarked to morph into Policy), the children of PolicyIdentifierList and the children of XACMLPolicyQuery. In the latter two cases it doesn't make sense to provide arguments for a parameterized policy. The first case has an "evaluation" aspect to it that the other two don't, and different element names and types can be justified.

So PolicyReference with optional arguments as the child of Policy and PolicyIdReference with no arguments as a child of PolicyIdentifierList or XACMLPolicyQuery.

steven-legg commented 5 months ago

Policy references were just URIs in XACML 1.0. This is all the discussion I could find in the archives regarding the change to IdReferenceType in XACML 2.0.

https://lists.oasis-open.org/archives/xacml/200310/msg00058.html https://lists.oasis-open.org/archives/xacml/200312/msg00062.html

The proposal was accepted in the TC conference call of Jan 8, 2004. The minutes don't record any detailed discussion.

cdanger commented 5 months ago

A potential objection to having a single policy reference type with optional arguments is that the parameters for parameterized policies can have default values so the arguments can be left out. A policy reference with no arguments could be a reference to a regular policy or it could be a reference to a parameterized policy using the default values. It isn't obvious what one is looking at without fetching the referenced policy.

OK but even if we have two different types of policy reference, still one needs to fetch the referenced policy in order to know which type of policy (parameterized or not) it is, and so which type of reference to use, and what arguments it expects in the reference if it is parameterized. Or at least you need to fetch some policy metadata / description.

A counter argument is that people shouldn't be dealing with the raw XML/JSON/YAML and should use better PAPs that do the looking for them.

Yes, I agree more with that counter argument. In #4 , we make sure the required Parameters are explicitly defined in the Policy with their DataTypes, so that PAPs have all they need to help and verify people use valid policy references with the proper arguments (with the right datatypes in particular).

cdanger commented 5 months ago

Policy references were just URIs in XACML 1.0. This is all the discussion I could find in the archives regarding the change to IdReferenceType in XACML 2.0.

https://lists.oasis-open.org/archives/xacml/200310/msg00058.html https://lists.oasis-open.org/archives/xacml/200312/msg00062.html

The proposal was accepted in the TC conference call of Jan 8, 2004. The minutes don't record any detailed discussion.

Thanks for digging this out. The MOTIVATING USE-CASE AND REQUIREMENT part in the first link is helpful I think. At least, I understand better the need for dedicated Version / EarliestVersion / LatestVersion attributes, especially with the analogy of shared libraries, which reminds me of Linux package dependency management and that makes sense to me. Also it says it has been requested by many developers (?) at the time.

So that's OK with me if we keep those Version attributes in policy references. Still I would like to change/extend Policy(Id)Reference type so that it can accept arguments for parameterized policies.

steven-legg commented 5 months ago

So that's OK with me if we keep those Version attributes in policy references. Still I would like to change/extend Policy(Id)Reference type so that it can accept arguments for parameterized policies.

Without knowing the details of the use cases I'm inclined to keep the version attributes as well. Some people had a use for them. However, we should change the essential URI from element content to an XML attribute to make way for child elements for optional arguments.

cdanger commented 5 months ago

Without knowing the details of the use cases I'm inclined to keep the version attributes as well. Some people had a use for them. However, we should change the essential URI from element content to an XML attribute to make way for child elements for optional arguments.

OK, so something like this? :

<xs:complexType name="IdReferenceType">
    <xs:complexContent>
        <xs:attribute name="Id" type="xs:anyURI" use="required"/>
        <xs:attribute name="Version" type="xacml:VersionMatchType" use="optional"/>
        <xs:attribute name="EarliestVersion" type="xacml:VersionMatchType" use="optional"/>
        <xs:attribute name="LatestVersion" type="xacml:VersionMatchType" use="optional"/>
    </xs:complexContent>
</xs:complexType>

This way, we can extend it to add optional arguments in the other policy reference type.

But also, from your previous comment...

So PolicyReference with optional arguments as the child of Policy and PolicyIdReference with no arguments as a child of PolicyIdentifierList or XACMLPolicyQuery.

... I had a closer look at PolicyIdentifierList, and it seems to me there is an opportunity here to improve the XML schema of the policy references in PolicyIdentifierList. Indeed, as opposed to references in other places, each policy reference in PolicyIdentifierList must identify the exact Version of the applicable policy and MUST NOT use the LatestVersion or EarliestVersion attributes (§5.49 of the spec). Therefore, this definition does not match the current IdReferenceType definition properly, since unlike IdReferenceType in this case, the Version attribute is mandatory and should rather be of VersionType instead of VersionMatchType, and there should not be any LatestVersion or EarliestVersion.

That's why I suggest we add a new XML type for references in PolicyIdentifierList, such as StaticIdReferenceType, and rename the IdReferenceType with VersionMatch attributes (Version, EarliestVersion, LatestVersion) to IdReferenceMatchType (or IdReferencePatternType if you prefer) to make the distinction more explicit: the latter is using regex/patterns to match the Version, whereas the StaticIdReferenceType is not. Still I'd like to keep IdReferenceType as the base type for all these different kinds of policy reference.

In short, this proposal means:

  1. Redefining the IdReferenceType as the following base type:

    <xs:complexType name="IdReferenceType" abstract="true">
    <xs:complexContent>
        <xs:attribute name="Id" type="xs:anyURI" use="required" />
    </xs:complexContent>
    </xs:complexType>
  2. For references in PolicyIdentifierList, define a new subtype StaticIdReferenceType with a mandatory (literal) Version that is an actual Version (not a VersionMatchType):

    
    <xs:complexType name="StaticIdReferenceType">
        <xs:complexContent>
            <xs:extension base="xacml:IdReferenceType">
                <xs:attribute name="Version" type="xacml:VersionType" use="required"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
``` _In fact, I would just replace PolicyIdentifierList altogether with just ``, which is semantically equivalent._ 3. For references in **XACMLPolicyQuery**, define a new subtype `IdReferenceMatchType` with the VersionMatch attributes (Version/EarliestVersion/LatestVersion) which are needed according to previous comment, so the type of reference is similar to the current IdReferenceType but we need a different name for the type, such as `IdReferenceMatchType` as explained earlier: ```xml ``` 4. For references in **Policies**, define the PolicyReferenceType as subtype of IdReferenceMatchType above with the optional arguments: ```xml ``` (If you'd like different names for the new reference types, feel free to suggest.)
steven-legg commented 5 months ago

I agree with the proposed restructuring with some minor quibbles.

In fact, I would just replace PolicyIdentifierList altogether with just <xs:element name="PolicyIdReference" type="xacml:StaticIdReferenceType" minOccurs="0" macOccurs="unbounded" />, which is semantically equivalent.

I agree that we don't need PolicyIdentifierList to wrap a list of policy references. However, the core specification makes the stylistic choice to reference top-level element declarations rather than use local element declarations. The top-level definition ought to be:

<xs:element name="PolicyIdReference" type="xacml:StaticIdReferenceType"/>

And the replacement for PolicyIdentifierList would be:

<xs:element ref="xacml:PolicyIdReference" minOccurs="0" maxOccurs="unbounded" />

The trouble is, both XACMLPolicyQueryType and PolicyIdentifierListType currently reference the top-level PolicyIdReference element, but the element types are not going to be the same, so we need two different top-level element names. PolicyIdReference says what it is, but not it's for, so I suggest we use something like ApplicablePolicyReference for use by ResultType (the parent of PolicyIdentifierList) and PolicyRequest for use by XACMLPolicyQueryType. We could also keep PolicyIdReference for XACMLPolicyQueryType since that usage is closer to the current definition of PolicyIdReference.

I would choose SpecificIdReferenceType or ExactIdReferenceType over the name StaticIdReferenceType.

cdanger commented 4 months ago

[...] The top-level definition ought to be:

<xs:element name="PolicyIdReference" type="xacml:StaticIdReferenceType"/>

And the replacement for PolicyIdentifierList would be:

<xs:element ref="xacml:PolicyIdReference" minOccurs="0" maxOccurs="unbounded" />

Allright, fine by me.

The trouble is, both XACMLPolicyQueryType and PolicyIdentifierListType currently reference the top-level PolicyIdReference element, but the element types are not going to be the same, so we need two different top-level element names. PolicyIdReference says what it is, but not it's for, so I suggest we use something like ApplicablePolicyReference for use by ResultType (the parent of PolicyIdentifierList) and PolicyRequest for use by XACMLPolicyQueryType. We could also keep PolicyIdReference for XACMLPolicyQueryType since that usage is closer to the current definition of PolicyIdReference.

OK then ApplicablePolicyReference in ResultType and PolicyIdReference in XACMLPolicyQueryType are fine by me.

Now I notice in the XACML spec the attribute name PolicyIdRef (resp. PolicySetIdRef) is used in PolicyCombinerParameters (resp. PolicySetCombinerParameters).
So why not use such shorter names for the top-level elements as well? That is to say: PolicyRef in Policy, PolicyIdRef in XACMLPolicyQuery, and ApplicablePolicyRef in Result.

I would choose SpecificIdReferenceType or ExactIdReferenceType over the name StaticIdReferenceType.

OK I would prefer something like ExactIdReferenceType in that case. But, in that spirit, I would go as far as ExactMatchIdReferenceType and rename the aforementioned IdReferenceMatchType to PatternMatchIdReferenceType (or RegexMatchIdReferenceType if you prefer) to make the difference even more obvious.

steven-legg commented 4 months ago

Now I notice in the XACML spec the attribute name PolicyIdRef (resp. PolicySetIdRef) is used in PolicyCombinerParameters (resp. PolicySetCombinerParameters). So why not use such shorter names for the top-level elements as well?

The shorter names for these attributes might have been to make them different from the element names. If we shorten the element names then we have two things called PolicyIdRef (one an attribute, one an element) that aren't exactly the same thing conceptually.

On the whole the standard has avoided abbreviating names, though "Id" is an obvious (albeit consistent) exception.

OK I would prefer something like ExactIdReferenceType in that case. But, in that spirit, I would go as far as ExactMatchIdReferenceType and rename the aforementioned IdReferenceMatchType to PatternMatchIdReferenceType (or RegexMatchIdReferenceType if you prefer) to make the difference even more obvious.

I don't mind the longer names, but would prefer PatternMatch... over RegexMatch...

cdanger commented 4 months ago

OK for PatternMatchIdReferenceType and keeping the long element names then.

cdanger commented 1 month ago

Summarizing the proposed changes to the schemas based on latest comments:

<!-- Changes to SAML Profile schema -->

<!-- XACMLPolicyQueryType modified -->
<complexType name="XACMLPolicyQueryType">
    <complexContent>
        <extension base="samlp:RequestAbstractType">
            <choice minOccurs="1" maxOccurs="unbounded">
                <element ref="xacml-context:Request"/>
                <!-- PolicyIdReference definition changed in the XACML schema (see down below)  -->
                <element ref="xacml:PolicyIdReference"/>
                <!-- PolicySetIdReference removed -->
            </choice>
        </extension>
    </complexContent>
</complexType>

<!-- Changes to XACML schema -->

<!-- PolicyIdReference used in a SAML XACMLPolicyQuery. Type changed to new PatternMatchIdReferenceType -->
<xs:element name="PolicyIdReference" type="xacml:PatternMatchIdReferenceType"/>
<!-- New IdReferenceType extension with Version pattern matching, to be used in Policies (PolicyReference) and XACMLPolicyQuery (PolicyIdReference). Same as old PolicyIdReferenceType except the Id is now an XML attribute, cf. IdReferenceType change down below. -->
<xs:complexType name="PatternMatchIdReferenceType">
   <xs:complexContent>
          <xs:extension base="xacml:IdReferenceType">
            <xs:attribute name="Version" type="xacml:VersionMatchType" use="optional"/>
            <xs:attribute name="EarliestVersion" type="xacml:VersionMatchType" use="optional"/>
            <xs:attribute name="LatestVersion" type="xacml:VersionMatchType" use="optional"/>
          </xs:extension>
   </xs:complexContent>
</xs:complexType>

<!-- ResultType changed -->
<xs:complexType name="ResultType">
  <xs:sequence>
      ...
          <!-- PoliyIdentifierList replaced with list of ApplicablePolicyReferences -->
      <xs:element ref="xacml:ApplicablePolicyReference" minOccurs="0" maxOccurs="unbounded" />
  </xs:sequence>
</xs:complexType>

<!-- Policy reference used in a Result's list of applicable policies -->
<xs:element name="ApplicablePolicyReference" type="xacml:ExactMatchIdReferenceType"/>
<!-- New IdReferenceType extension with fixed Version, to be used in Result (ApplicablePolicyReference), as opposed to PatternMatchIdReferenceType which uses Version pattern matching. -->
<xs:complexType name="ExactMatchIdReferenceType">
        <xs:complexContent>
            <xs:extension base="xacml:IdReferenceType">
                <xs:attribute name="Version" type="xacml:VersionType" use="required"/>
            </xs:extension>
        </xs:complexContent>
</xs:complexType>

<!-- PolicyType changed to use new PolicyReference instead of Policy(Set)IdReference (see issue 11 for details) -->
<xs:complexType name="PolicyType">
    <xs:sequence>
       ...
        <xs:choice minOccurs="0" maxOccurs="unbounded">
           ...
           <!-- PolicyIdReference replaced with PolicyReference -->
            <xs:element ref="xacml:PolicyReference"/>
            ...
        </xs:choice>
        ...
    </xs:sequence>
    ...
</xs:complexType>

<!-- Policy reference to be used inside Policies, takes optional arguments for parameterized policies -->
<xs:element name="PolicyReference" type="xacml:PolicyReferenceType"/>
<xs:complexType name="PolicyReferenceType">
   <xs:complexContent>
          <xs:extension base="xacml:PatternMatchIdReferenceType">
            <xs:sequence>
              <!-- Optional argument(s) to the referenced policy (parameterized policy) -->
              <xs:element ref="xacml:Expression" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
          </xs:extension>
   </xs:complexContent>
</xs:complexType>

<!-- IdReferenceType URI changed to an XML attribute to allow extensions with optional attributes and arguments (ExactMatchIdReferenceType, PatternMatchIdReferenceType, PolicyIdReferenceType, PolicyReferenceType)  -->
<xs:complexType name="IdReferenceType" abstract="true">
    <xs:complexContent>
        <xs:attribute name="Id" type="xs:anyURI" use="required" />
    </xs:complexContent>
</xs:complexType>

<!-- PolicyIdentifierList removed -->
<!--
<xs:element name="PolicyIdentifierList" type="xacml:PolicyIdentifierListType"/>
<xs:complexType name="PolicyIdentifierListType">
  <xs:choice minOccurs="0" maxOccurs="unbounded">
    <xs:element ref="xacml:PolicyIdReference"/>
    <xs:element ref="xacml:PolicySetIdReference"/>
  </xs:choice>
</xs:complexType>
-->
steven-legg commented 1 month ago

Summarizing the proposed changes to the schemas based on latest comments

That looks right.

If we chose a different name for PolicyIdReference, say PolicyMatch or PolicyMatchReference, then we could shorten every "...IdReference..." to "...Reference...".