0

I am new to XACML and I would be grateful if you can help me with one problem I encountered. I use AuthzForce Core PDP (version 17.1.2). I am wondering what is the correct approach of representing complex data types in XACML.

Example

Access should be granted if PIP response contains any person whose name is present in names array from request and salary of that person is higher than salary provided in request.

Request

names = ["Eric", "Kyle"]
salary = 1500

PIP response

[
  {
    "name": "Kyle",
    "salary": 1000
  },
  {
    "name": "Kenny",
    "salary": 2000
  },
  {
    "name": "Eric",
    "salary": 4000
  },
  {
    "name": "Stan",
    "salary": 3000
  }
]

Access will be granted because PIP response contains person with name Eric and his salary is higher than 1500.

My implementation To represent PIP response I ended up with creating custom type by extending StringParseableValue class from AuthzForce. For above mentioned logic I use attribute designator in xml and have coresponding attribute provider (class extending BaseNamedAttributeProvider) in Java performing PIP call.

I also wrote two custom functions:

  1. Find people with higher salary than provided in one param (returns filtered list)
  2. Get person name (returns string) And using those functions and standard function I wrote policy and it works.

However my solution seems to be overcomplicated. I suppose what I did can be achieved by using only standard functions. Additionally if I wanted to define hardcoded bag of people inside other policy single element would look like this:

<AttributeValue DataType="person">name=Eric@@@salary=4000</AttributeValue>

There is always possibility that parsing of such strings might fail.

So my question is: What is a good practice of representing complex types like my PIP response in XACML using Authzforce? Sometimes I might need to pass more complex data in the request and I saw example in XACML specification showing passing such data inside <Content> element.

  • Where do you get the info in the PIP response (names and salaries) from ? SQL or NoSQL database ? REST service ? Does it support any query language ? – cdan Aug 13 '22 at 21:42
  • PIP is REST service in my case. The response I attached is more complicated in a real scenario. I use JSON path library to extract an array of objects from the response body, next I deserialize it to List and return AttributeBag using Bags.newAttributeBag method btw I will have a lot of PIPs returning responses having various structures (but in most cases, it will be array of strings). – tomasz0801 Aug 13 '22 at 22:41

1 Answers1

0

Creating a new XACML data-type - and consequently new XACML function(s) to handle that new data-type - seems a bit overkill indeed. Instead, you may improve your PIP (Attribute Provider) a little bit, so that it returns only the results for the employees named in the Request, and only their salaries (extracting them from the JSON using JSON path) returned as a bag of integers.

Then, assuming this PIP result is set to the attribute employee_salaries in your policy (bag of integers) for instance, and min_salary is the salary in the Request, it is just a matter of applying any-of(integer-less-than, min_salary, employee_salaries) in a Condition. (I'm using short names for the functions by convenience, please refer to the XACML 3.0 standard for the full identifiers.)

Tips to improve the PIP:

  1. One issue here is performance (scalability, response time / size...) because if you have hundreds even thousands of employees, it is overkill to get the whole list from the REST service over and over, all the more as you need only a small subset (the names in the Request). Instead, you may have some way to request the REST service to return only a specific employees, using query parameters; an example using RSQL (but this depends on the REST service API):
HTTP GET http://rest-service.example.com/employees?search=names=in=($employee_names)

... where you set the $employee_names variable to (a comma-separated list of) the employee names from the Request (e.g. Eric,Kyle). You can get these in your AttributeProvider implementation, from the EvaluationContext argument of the overriden get(...) method (EvaluationContext#getNamedAttributeValue(...)).

Then you can use a JSON path library (as you did) to extract the salaries from the JSON response (so you have only the salaries of the employees named in the Request), using this JSON path for instance (tested with Jayway):

$[*].salary
  1. If the previous option is not possible, i.e. you have no way of filtering employees on the REST API, you can always do this filtering in your AttributeProvider implementation with the JSON path library, using this JSON path for instance (tested with Jayway against your PIP response):
$[?(@.name in [$employee_names])].salary

... where you set the $employee_names variable like in the previous way, getting the names from the EvaluationContext. So the actual JSONpath after variable replacement would be something like:

$[?(@.name in [Eric,Kyle])].salary

(You may add quotes to each name to be safe.)

All things considered, if you still prefer to go for new XACML data-type (and functions), and since you seem to have done most of the work (impressive btw), I have a suggestion - if doable without to much extra work - to generalize the Person data-type to more generic JSON object datatype that could be reused in any use case dealing with JSON. Then see whether the extra functions could be done with a generic JSONPath evaluation function applied to the new JSON object data-type. This would provide a JSON equivalent to the standard XML/XPath data-type and functions we already have in XACML, and this kind of contribution would benefit the AuthzForce community greatly.

For the JSON object data-type, actually you can use the one in the testutils module as an example: CustomJsonObjectBasedAttributeValue which has been used to test support of JSON objects for the GeoXACML extension.

cdan
  • 3,470
  • 13
  • 27
  • 1
    Thank you for your really exhaustive answer. Performance shouldn't be an issue, because PIP returns rather a small number of entries (Employee type was used only as an example). Additionally, I can cache those data so further invocations take a few milliseconds. PIP is managed by other team so changing contract might be pretty hard. I think I will end up filtering data in the attribute provider to avoid using custom type. The type I created is far from being generic, but it is possible I will need a more generic JSON type in the future. – tomasz0801 Aug 24 '22 at 21:46