Page 1
Standard

TGIF XACML – What’s a XACML target?

Today’s Friday, the weather has been amazingly nice these past few weeks in Stockholm which is all the more surprising since September is on the slope down to darker, wetter, and colder days. The weekend ahead looks promising. I’ll be heading out to fellow colleague, Andreas’ summer house out in the archipelago.

The view from the Axiomatics offices towards Skeppsholmen and AF Chapman

The view from the Axiomatics offices towards Skeppsholmen and AF Chapman


But before I walk out the door, I thought I’d share a bit of XACML know-how to chew on over the next couple of days. In the training sessions we regularly give at Axiomatics, attendees often ask what a target is.

XACML Target

Definition

A target is an element of the XACML policy language. It can occur in policy sets, policies, and rules. The target is used to define their scope. The scope defines when the policy (set) / rule will trigger. For instance, for a rule to trigger and yield a Permit decision for managers in Greece, the target would have to contain two attribute matches:

  • role==manager, and
  • userLocation==Greece

There can be any number of matches. A match is always between an attribute (role, department, location, classification…) and a value. Matches can then be assembled together using logical operands (AND, OR).

Where can I use the target?

Targets can be used in:

  • Policy Set elements
  • Policy elements
  • Rule elements

Example

The following uses the ALFA syntax. You can download the plugin for free from the Axiomatics website. Check out YouTube for a video example.

/**
 * A user in Greece can read a document in the Greece region
 */
 policy readDocument{
 	target clause actionId=="read" and resourceType=="document"
 	apply firstApplicable
 	rule allowReadIfCorrectRegion{
 		target clause userLocation=="Greece" and documentRegion=="Greece"
 		permit
 	}
 }

The above example will yield a Permit if and only if the user trying to read a document based in Greece is also based in Greece.

Conclusion

I hope this simple example helps to understand the XACML policy language. Stay tuned for more TGIF XACML tidbits.

Previously in TGIF XACML…

Previous tidbits can be found here:

Standard

How to send a XACML request using Perl

In a previous post, I mention how I used cURL to send a XACML request to an Axiomatics XACML Policy Decision Point (PDP). My goal, however, wasn’t to use cURL but rather whip up a sample in Perl.
Perl is perhaps my third love in terms of programming languages. As a kid, I learned programming with Pascal. Later, as a teen, I went across to web programming and PHP. In my first uni. student placement I was tasked with writing Perl code which opened up a whole new world of scripting.
These days, most of what I do revolves around XACML, the eXtensible Access Control Markup Language. XACML defines an architecture to apply fine-grained, externalized authorization to any type of application. Typically, the customers I deal with at Axiomatics want to apply XACML to Java or C#. This entails writing policy enforcement points (PEP) in Java or .NET. Occasionally though, we do get requests for Perl. And so, on a flight back from a customer visit, I googled around for the latest in Perl and hacked a very simple example together.
To get running, I used

It was actually very quick and easy to test out the Perl PEP. This is what it looks like:

#!/usr/bin/perl -w

use strict;

use LWP::UserAgent;
use HTTP::Request::Common;

my $userAgent = LWP::UserAgent->new(agent => 'perl post');
$userAgent->credentials("localhost:8280","Axiomatics PDP",'pdp-user','password');
my $soapStartElement = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">
<soap:Body>
<irc:AccessQuery3 xmlns:irc=\"http://axiomatics.com/delegent/pdpsimple/v5/AccessQuery3\">
";
my $soapCloseElement = "</irc:AccessQuery3>
</soap:Body>
</soap:Envelope>";
my $xacmlRequest = "<xacml-ctx:Request ReturnPolicyIdList=\"true\" CombinedDecision=\"false\" xmlns:xacml-ctx=\"urn:oasis:names:tc:xacml:3.0:core:schema:wd-17\">
   <xacml-ctx:Attributes Category=\"urn:oasis:names:tc:xacml:3.0:attribute-category:resource\" >
   </xacml-ctx:Attributes>
   <xacml-ctx:Attributes Category=\"urn:oasis:names:tc:xacml:3.0:attribute-category:action\" >
   </xacml-ctx:Attributes>
   <xacml-ctx:Attributes Category=\"urn:oasis:names:tc:xacml:3.0:attribute-category:environment\" >
   </xacml-ctx:Attributes>
   <xacml-ctx:Attributes Category=\"urn:oasis:names:tc:xacml:1.0:subject-category:access-subject\" >
      <xacml-ctx:Attribute AttributeId=\"urn:oasis:names:tc:xacml:1.0:subject:subject-id\" IncludeInResult=\"true\">
         <xacml-ctx:AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">alice</xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
   </xacml-ctx:Attributes>
</xacml-ctx:Request>";

my $response = $userAgent->request(POST 'http://localhost:8280/asm-pdp/pdp',
Content_Type => 'text/xml',
Content => ($soapStartElement.$xacmlRequest.$soapCloseElement));

print $response->error_as_HTML unless $response->is_success;

print $response->as_string;

Enjoy!

Standard

How to send a XACML request using cURL – the world’s smallest Policy Enforcement Point

Recently, I’ve been asked to write a policy enforcement point (PEP) in Perl. I haven’t touched Perl in a long while but I remember having had fun using it to parse documents on a file system back in 2003 when working at the Natural Languages Lab at BT Adastral Park.
I started looking around at different resources. The obvious ones are:

  • http://www.perl.org/: the home of all Perl resources.
  • ActiveState Perl: possibly the de facto Perl distribution
  • Perlmonks: a great Perl forum where I used to hang out, and
  • Perl for Eclipse: EPIC, the Perl Editor and IDE for Eclipse – pretty much all I do these days is in and around Eclipse (from SQL and LDAP to ALFA, the Axiomatics Language for Authorization) so it seemed natural to add Perl to my Eclipse Swiss army knife.

Then, of course, it didn’t take me long to stumble upon cURL. cURL is one of those tools you just know, a bit like wget or basic Linux / Unix commands.

I then realized I could simply use cURL to post a XACML request to a Policy Decision Point. And that’s exactly what I tried. I had to fiddle around with the different options before I got it right. Here’s the outcome:

C:\temp>curl -X POST -H 'Content-type:text/xml' -T soap-xacml-request.xml https://localhost:8443/asm-pdp/pdp --cacert pdp.b64.cer --user pep:password
Let’s have a look at the different options:

  • -X : use this to indicate the HTTP method, i.e. POST in this case.
  • -H : use this to indicate custom headers, in this case Content-type:text/xml.
  • -T : use this to point to the file containing the payload to be sent, i.e. the XACML request optionally wrapped in a SOAP request if the targeted service is SOAP-based.
  • –cacert : use this to indicate the trusted certificate. Download the target server’s public key and use that in PEM format (base 64-encoded).
  • –user : use this to indicate the username and password to be used, if any, e.g. in the case of HTTP Basic Authentication.

Great, I can now send a XACML request in less characters than a tweet requires. Sure enough, playing around with cURL diverted me from my original intent – writing a PEP in Perl. I guess PPEP will have to wait…

Here’s the sample XACML request I sent:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <irc:AccessQuery3
            xmlns:irc="http://axiomatics.com/delegent/pdpsimple/v5/AccessQuery3">
            <xacml-ctx:Request ReturnPolicyIdList="false"
                CombinedDecision="false"
                xmlns:xacml-ctx="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17">
                <xacml-ctx:Attributes
                    Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
                    <xacml-ctx:Attribute AttributeId="action-id"
                        IncludeInResult="true">
                        <xacml-ctx:AttributeValue
                            DataType="http://www.w3.org/2001/XMLSchema#string">
                            view
                        </xacml-ctx:AttributeValue>
                    </xacml-ctx:Attribute>
                </xacml-ctx:Attributes>
                <xacml-ctx:Attributes
                    Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource">
                    <xacml-ctx:Attribute
                        AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-type"
                        IncludeInResult="true">
                        <xacml-ctx:AttributeValue
                            DataType="http://www.w3.org/2001/XMLSchema#string">
                            book
                        </xacml-ctx:AttributeValue>
                    </xacml-ctx:Attribute>
                </xacml-ctx:Attributes>
                <xacml-ctx:Attributes
                    Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
                    <xacml-ctx:Attribute AttributeId="username"
                        IncludeInResult="true">
                        <xacml-ctx:AttributeValue
                            DataType="http://www.w3.org/2001/XMLSchema#string">
                            Alice
                        </xacml-ctx:AttributeValue>
                    </xacml-ctx:Attribute>
                </xacml-ctx:Attributes>
            </xacml-ctx:Request>
        </irc:AccessQuery3>
    </soap:Body>

and the response:

<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns6:AccessQuery3Response xmlns:ns2="http://axiomatics.com/delegent/pdpsimple/v5/TraceAccessQuery3" xmlns:ns3="http://axiomatics.com/delegent/pdpsimple/v5/InvalidateAttributeCache" xmlns:ns4="http://axiomatics.com/delegent/pdpsimple/v5/TraceAccessQuery2" xmlns:ns5="http://axiomatics.com/delegent/pdpsimple/v5/AccessQuery2" xmlns:ns6="http://axiomatics.com/delegent/pdpsimple/v5/AccessQuery3" xmlns:ns7="urn:oasis:names:tc:xacml:2.0:context:schema:os" xmlns:ns8="urn:oasis:names:tc:xacml:2.0:policy:schema:os" xmlns:ns9="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" xmlns:ns10="http://axiomatics.com/delegent/pdpsimple/v5/faults"><xacml-ctx:Response xmlns:xacml-ctx="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17">
  <xacml-ctx:Result>
    <xacml-ctx:Decision>Deny</xacml-ctx:Decision>
    <xacml-ctx:Status>
      <xacml-ctx:StatusCode Value="urn:oasis:names:tc:xacml:1.0:status:ok"/>
    </xacml-ctx:Status>
    <xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
      <xacml-ctx:Attribute AttributeId="action-id" IncludeInResult="true">
        <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">
                            view
                        </xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
    </xacml-ctx:Attributes>
    <xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource">
      <xacml-ctx:Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-type" IncludeInResult="true">
        <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">
                            book
                        </xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
    </xacml-ctx:Attributes>
    <xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
      <xacml-ctx:Attribute AttributeId="username" IncludeInResult="true">
        <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">
                            Alice
                        </xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
    </xacml-ctx:Attributes>
  </xacml-ctx:Result>
</xacml-ctx:Response></ns6:AccessQuery3Response></S:Body></S:Envelope>
Standard

Call out to a XACML Policy Decision Point (PDP) from PHP

Today, I have the pleasure to invite a fellow colleague, Patrick McDowell, to post on my blog. Today’s topic is around reaching out to other languages other than just Java and C# for XACML-based authorization. Today’s choice? PHP, naturellement as both Patrick and I are huge WordPress fans.

If you have been programming in PHP it is very likely that you have interacted with an external authentication service. For example Google and Facebook provide external authentication services that people can use to allow other providers to authenticate users for you using standard protocols such as SAML, OAuth, and OpenID.
Once a user has been authenticated, we then need to determine what that user is authorized to do inside of an application or service. This authorization logic can be externalized and defined using a standard language called XACML.
XACML stands for eXtensible Access Control Markup Language. The standard defines a declarative access control policy language implemented in XML and a processing model describing how to evaluate authorization requests according to the rules defined in policies.
Unlike the typical role-based security methodology used in many applications XACML authorization decisions are made in real time, and are made based on attributes about the user, the resource, and the context. For example a bank teller might have access to an account but should not be permitted to access his or her own account; the teller should not have access to accounts outside of his or her bank. XACML policies can be evaluated in real time to determine whether the teller should be permitted to access an account.
Additionally authorization decisions are made externally from the application, therefore security policy is not hardcoded into the application, which makes it easier for security policies to be changed. and Security administrators gain easier access to the authorization logic.
XACML requests include:

  • Subject
  • Action
  • Resource
  • Environment

And the XACML Policy Server (PDP, aka Policy Decision Point), will return:

  • Decision (Deny, Permit, Indeterminate, Not Applicable)
  • Status
  • Obligations or Advice

To keep this simple, we are simply going to ask the XACML Authorization server to confirm that:
Users with Teller Role (Subject), can View (Action), Bank Accounts (Resource)
This request in raw XACML looks like this:

<xacml-ctx:Request ReturnPolicyIdList="true" CombinedDecision="false" xmlns:xacml-ctx="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17">
   <xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" >
      <xacml-ctx:Attribute AttributeId="http://www.axiomatics.com/acs/role" IncludeInResult="true">
         <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">teller</xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
   </xacml-ctx:Attributes>
   <xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" >
      <xacml-ctx:Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" IncludeInResult="true">
         <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">view</xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
   </xacml-ctx:Attributes>
   <xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment" >
   </xacml-ctx:Attributes>
   <xacml-ctx:Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" >
      <xacml-ctx:Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" IncludeInResult="true">
         <xacml-ctx:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">bank account</xacml-ctx:AttributeValue>
      </xacml-ctx:Attribute>
   </xacml-ctx:Attributes>
</xacml-ctx:Request>

The same request can be produced in PHP with SOAP like this:

$regReq = new stdClass();

$regReq->Version = "3.0";
$regReq->ID = "abcde1234";
$regReq->ReturnContext = true;
$regReq->Request = new stdClass();
$regReq->Request->ReturnPolicyIdList="true";
$regReq->Request->CombinedDecision="false";

$regReq->Request->Attributes = array();

$regReq->Request->Attributes[0]= new stdClass();
$regReq->Request->Attributes[0]->Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject";
$regReq->Request->Attributes[0]->Attribute = new stdClass();
$regReq->Request->Attributes[0]->Attribute->AttributeId = "http://www.axiomatics.com/acs/role";
$regReq->Request->Attributes[0]->Attribute->AttributeValue = new stdClass();
$regReq->Request->Attributes[0]->Attribute->AttributeValue->DataType="http://www.w3.org/2001/XMLSchema#string";
$regReq->Request->Attributes[0]->Attribute->AttributeValue->any="teller";

$regReq->Request->Attributes[1]= new stdClass();
$regReq->Request->Attributes[1]->Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"; 
$regReq->Request->Attributes[1]->Attribute = new stdClass();
$regReq->Request->Attributes[1]->Attribute->AttributeId = "urn:oasis:names:tc:xacml:1.0:action:action-id";
$regReq->Request->Attributes[1]->Attribute->AttributeValue = new stdClass();
$regReq->Request->Attributes[1]->Attribute->AttributeValue->DataType="http://www.w3.org/2001/XMLSchema#string";
$regReq->Request->Attributes[1]->Attribute->AttributeValue->any="view";

$regReq->Request->Attributes[2]= new stdClass();
$regReq->Request->Attributes[2]->Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"; 
$regReq->Request->Attributes[2]->Attribute = new stdClass();
$regReq->Request->Attributes[2]->Attribute->AttributeId = "urn:oasis:names:tc:xacml:1.0:resource:resource-id";
$regReq->Request->Attributes[2]->Attribute->AttributeValue = new stdClass();
$regReq->Request->Attributes[2]->Attribute->AttributeValue->DataType="http://www.w3.org/2001/XMLSchema#string";
$regReq->Request->Attributes[2]->Attribute->AttributeValue->any="bank account";
 
$regReq->Request->Attributes[3]= new stdClass();
$regReq->Request->Attributes[3]->Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment";

The following PHP code creates the WS client and sends the request to the PDP.

ini_set('soap.wsdl_cache_enabled', 0); // Turn off the cache if you like
$client = new SoapClient("http://axiomatics:8080/asm-pdp/pdp?WSDL", Array("trace" => 1));
$result = $client->AccessQuery3($regReq);

The result returns a stdClass like this:

stdClass Object ( [Response] => stdClass Object ( [Result] => stdClass Object ( [Decision] => Permit [Status] => stdClass Object ( [StatusCode] => stdClass Object ( [Value] => urn:oasis:names:tc:xacml:1.0:status:ok ) ) ) ) )

The response to this request will return an object called Result with a field labeled Decision set to Permit, as well as other information about the request such as Obligations / Advice and information about the request.
To handle the response in PHP, all you need is the following code snippet:

if ( $result->Response->Result->Decision == "Permit") { 
 echo "Permit.. Tellers can view bank accounts";
}  

The response does depend on the policy, and if the request did not find an appropriate target it is possible the response could be NotApplicable, which essentially means the Policy Decision Point (PDP), did not have enough information to make a decision.
The XACML Policy is also written in XML, and look like this in Raw XML:

<xacml3:Policy xmlns:xacml3="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="http://www.axiomatics.com/automatic-unique-id/5ec8c01d-456c-4800-b28b-ad3d289ecba3" Version="1.0" RuleCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:deny-unless-permit">
<xacml3:PolicyDefaults><xacml3:XPathVersion>http://www.w3.org/TR/1999/REC-xpath-19991116</xacml3:XPathVersion></xacml3:PolicyDefaults>
  <xacml3:Target>
    <xacml3:AnyOf>
      <xacml3:AllOf>
        <xacml3:Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
          <xacml3:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">bank account</xacml3:AttributeValue>
          <xacml3:AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"  AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/>
        </xacml3:Match>
        <xacml3:Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
          <xacml3:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">view</xacml3:AttributeValue>
          <xacml3:AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"  AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/>
        </xacml3:Match>
        <xacml3:Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
          <xacml3:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">teller</xacml3:AttributeValue>
          <xacml3:AttributeDesignator Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"  AttributeId="http://www.axiomatics.com/acs/role" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/>
        </xacml3:Match>
      </xacml3:AllOf>
    </xacml3:AnyOf>
  </xacml3:Target>
  <xacml3:Rule RuleId="51179cb3-5319-4a35-a13e-ac1db27b5d93" Effect="Permit">
    <xacml3:Description>doctor can view medicalrecord</xacml3:Description>
    <xacml3:Target/>
  </xacml3:Rule>
  <xacml3:Rule RuleId="a2af1648-41c0-4843-ba4f-c1284d367957" Effect="Deny">
    <xacml3:Target/>
  </xacml3:Rule>
</xacml3:Policy>

If you don’t like working with raw XML, Axiomatics offers an Eclipse Plug-in which uses a “Pseudocode” called ALFA (Axiomatics Language for Authorization) which makes writing these policies much simpler. It can be downloaded for free here.

Standard

A neat MS SQL treat: convert from count(*) to a bit (or boolean)

I was busy writing a sample application for a retail company where I wanted to express a XACML authorization policy that would state that a user can sell an item if it hasn’t already been sold.
I knew whether the item was sold by simply running a SQL PIP retrieving the count(*) of that item id in the sales contracts. But I wanted to have a boolean attribute in the XACML policy:
A user can sell if the item is not sold (i.e. sold==false). So I went looking around for a means to convert count(*) into a MS SQL bit (the boolean datatype).

And the answer is:

select cast(count(*) as bit) as sold from salecontracts where identifier='9700E2EA-8545-4F26-91A1-1F5E7953E3A4'