Working with XACML 3.0 policies for fine-grained authorization - 1

With this post I am to share few things I learnt on XACML 3.0. This will be helpful to you if you are newly learning XACML or already familiar with XACML 2.0 and trying to upgrade to XACML 3.0. Going through the XACML 3.0 OASIS specification and trying out few sample polices and requests observing the responses was the best way to learn this I have experienced. So I will share the samples I tried out. You can try out the same with WSO2 Identity Server which supports XACML 3.0 specification with Balana open course engine. My previous blog post, Try out XACML policies with WSO2 Identity Server will help you to get start with it. This will be the first post of a series of posts and will carry the corresponding XACML 3.0 policies for the sample XACML 2.0 policies mentioned in the blog at references.

Let's go directly to a sample.

Imagine a requirement where we want to provide fine-grained authorized access to the service "http://localhost:8280/services/echo/" letting only the users of admin group read it. Any other requests should fail. So we can clearly identify the entries of the XACML policy as follows.

Resource: http://localhost:8280/services/echo/
Action: read
Group: admin,  Here the group is not a standard category, but a customized one, that we need to define our selves.

Following is the XACML 3.0 policy I wrote for the requirement,

<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"  PolicyId="2" RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable" Version="1.0">
   <Description>sample policy</Description>
   <Target></Target>
   <Rule Effect="Permit" RuleId="primary-group-customer-rule">
      <Target>
         <AnyOf>
            <AllOf>
               <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match">
                  <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">http://localhost:8280/services/echo/</AttributeValue>
                  <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
               </Match>
               <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
                  <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
                  <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
               </Match>
            </AllOf>
         </AnyOf>
      </Target>
      <Condition>
         <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-subset">
            <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag">
               <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue>
            </Apply>
            <AttributeDesignator AttributeId="group" Category="urn:oasis:names:tc:xacml:3.0:group" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"></AttributeDesignator>
         </Apply>
      </Condition>
   </Rule>
   <Rule Effect="Deny" RuleId="deny-rule"></Rule>
</Policy> 

If we first look at the target element, it has an AllOf element inside AnyOf element. In general words, 'AnyOf' behaves similar to 'OR' function and 'AllOf' behaves similar to 'AND' function over the child elements inside them. So here the Target is hit only if the request is to read the given resource inside the 'Match' elements. This is not enough as the rule says. In order to make the rule effect is effective the condition needs to be satisfied too, which says the request should be made by a user in the 'admin 'group category. Second is to deny any other requests that's not handled by the first rule.
Cheers we have defined the rule now. Let's check this whether it is behaving as we expect.
Here is the first Request,
It is from,
a user in admin group, to read the resource 'http://localhost:8280/services/echo/'. It carries an additional detail the subject as which is admin, but not necessary for our defined policy. So as we can see this should be Permitted.


<Request xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" CombinedDecision="false" ReturnPolicyIdList="false">
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
    </Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue>
    </Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">http://localhost:8280/services/echo/</AttributeValue>
    </Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:3.0:group">
    <Attribute AttributeId="group" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue>
    </Attribute>
</Attributes>
</Request>

Received Response:
<Response>
<Result>
<Decision>Permit</Decision>
<Status>
<StatusCode Value="urn:oasis:names:tc:xacml:1.0:status:ok"/>
</Status>
</Result>
</Response> 
Cheers! It's permitted. Well still we have to check whether other requests are denied too. On a side note, ideally the category group of the request should come with claim-management, but for the moment we have handled it as if request provide the all details. Following are few other sample requests with expects response.

  • Admin of business group tries to read the resource 'http://localhost:8280/services/echo/'. Response: Deny
<Request xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" CombinedDecision="false" ReturnPolicyIdList="false">
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
    </Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue>
    </Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">http://localhost:8280/services/echo/</AttributeValue>
    </Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:3.0:group">
    <Attribute AttributeId="group" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">business</AttributeValue>
    </Attribute>
</Attributes>
</Request>

  •  A user of 'admin' group tries to read the resource : http://localhost:8280/services/test/.  Response: Deny
<Request xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" CombinedDecision="false" ReturnPolicyIdList="false">
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
    </Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue>
    </Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">http://localhost:8280/services/test/</AttributeValue>
    </Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:3.0:group">
    <Attribute AttributeId="group" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue>
    </Attribute>
</Attributes>
</Request> 

  •   A user belonging to both admin group and business group, tries to read resource: 'http://localhost:8280/services/echo/'. Response:Permit
 <Request xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" CombinedDecision="false" ReturnPolicyIdList="false">
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
    </Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue>
    </Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">http://localhost:8280/services/echo/</AttributeValue>
    </Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:3.0:group">
    <Attribute AttributeId="group" IncludeInResult="false">
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue>
        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">business</AttributeValue>
    </Attribute>
</Attributes>
</Request>

References: http://blog.facilelogin.com/search/label/XACML
Corresponding XACML 2.0 policy - FacileLogin

Hope this post has been helpful to you. You can also refer following links to get familiar with changes from XACML 2.0 or to XACML 3.0.
  1. https://wiki.oasis-open.org/xacml/DifferencesBetweenXACML2.0AndXACML3.0 
  2. http://xacmlinfo.com/2012/07/12/what-is-new-with-xacml-3-0/ 
The next post of this series is here, http://pushpalankajaya.blogspot.com/2013/06/writing-xacml-30-policies-diverse-rules.html which provides a sample XACML policy that defines authorization for two distinct operations in different manner.




Popular posts from this blog

Signing SOAP Messages - Generation of Enveloped XML Signatures

How to convert WSDL to Java

How to Write a Custom User Store Manager - WSO2 Identity Server 4.5.0