In XACML obligations why is the "fulfillOn" Attribute Reserved for Permit & Deny only? - authorization

Wonder why the WSO2 Balana framework at the Obligations statements only accepts fulfillOn argument for "Permit ", or "Deny" conditions, but ignores the "Not applicable" result, which also could be interesting to intercept and document in the logic flow to assist the policy debug process.
In source of Balana ObligationExpression.java we find:
if("Permit".equals(effect)){
fulfillOn = Result.DECISION_PERMIT;
} else if("Deny".equals(effect)){
fulfillOn = Result.DECISION_DENY;
} else {
throw new ParsingException("Invalid FulfillOn : " + effect);
}
What is your opinion about it, is this logic working correctly?

This is by spec. The XACML specification only allows obligations and advice to be returned on either of Permit or Deny. You have to keep that in mind when you build your policies. See below and here.
7.18 Obligations and advice
A rule, policy, or policy set may contain one or more obligation or advice expressions. When such a rule, policy, or policy set is evaluated, the obligation or advice expression SHALL be evaluated to an obligation or advice respectively, which SHALL be passed up to the next level of evaluation (the enclosing or referencing policy, policy set, or authorization decision) only if the result of the rule, policy, or policy set being evaluated matches the value of the FulfillOn attribute of the obligation or the AppliesTo attribute of the advice. If any of the attribute assignment expressions in an obligation or advice expression with a matching FulfillOn or AppliesTo attribute evaluates to “Indeterminate”, then the whole rule, policy, or policy set SHALL be “Indeterminate”. If the FulfillOn or AppliesTo attribute does not match the result of the combining algorithm or the rule evaluation, then any indeterminate in an obligation or advice expression has no effect.
As a consequence of this procedure, no obligations or advice SHALL be returned to the PEP if the rule, policies, or policy sets from which they are drawn are not evaluated, or if their evaluated result is "Indeterminate" or "NotApplicable", or if the decision resulting from evaluating the rule, policy, or policy set does not match the decision resulting from evaluating an enclosing policy set.
If the PDP's evaluation is viewed as a tree of rules, policy sets and policies, each of which returns "Permit" or "Deny", then the set of obligations and advice returned by the PDP to the PEP will include only the obligations and advice associated with those paths where the result at each level of evaluation is the same as the result being returned by the PDP. In situations where any lack of determinism is unacceptable, a deterministic combining algorithm, such as ordered-deny-overrides, should be used.
Also see Section 7.2.
Allowing for obligations & advice on NotApplicable would be messy. Imagine the following policy structure:
PolicySet Main Policy
Policy Allow managers to view documents + obligation A on NotApplicable
Policy Allow employees to view documents in their own department + obligation B on NotApplicable
Policy Allow publishers to view and publish documents + obligation C on Permit
Imagine the request coming in is:
Request: can Alice the publisher publish doc #123?
In your world, the response would (could) be: Permit + obligations A,B,C
It doesn't really make any sense.

Related

Representing complex data types in XACML using Authzforce

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:
Find people with higher salary than provided in one param (returns filtered list)
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.
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:
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
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.

REST GET mehod: Can return a list of enriched resources?

I have a doubt when I'm designing a REST API.
Consider I have a Resource "Customer" with two elements in my server, like this:
[
{
name : "Mary",
description : "An imaginary woman very tall."
},
{
name : "John",
description : "Just a guy."
}
]
And I want to make an endpoint, that will accept a GET request with a query. The query will provide a parameter with a value that will make an algorithm count how many occurrences for this text are there in all of its parameters.
So if we throw this request:
GET {baseURL}/customers?letters=ry
I should get something like
[
{
name : "Mary",
description : "An imaginary woman very tall.",
count : 3
},
{
name : "John",
description : "Just a guy.",
count : 0
}
]
Count parameter can not be included in the resource scheme as will depend on the value provided in the query, so the response objects have to be enriched.
I'm not getting a list of my resource but a modified resource.
Although it keeps the idempotent condition for GET Method, I see it escapes from the REST architecture concept (even the REST beyond CRUD).
Is it still a valid endpoint in a RESTful API? or should I create something like a new resource called "ratedCustomer"?
REST GET mehod: Can return a list of enriched resources?
TL;DR: yes.
Longer answer...
A successful GET request returns a representation of a single resource, identified by the request-target.
The fact that the information used to create the representation of the resource comes from multiple entities in your domain model, or multiple rows in your database, or from reports produced by other services... these are all implementation details. The HTTP transfer of documents over a network application doesn't care.
That also means that we can have multiple resources that include the same information in their representations. Think "pages in wikipedia" that duplicate each others' information.
Resource identifiers on the web are semantically opaque. All three of these identifiers are understood to be different resources
/A
/A?enriched
/B
We human beings looking at these identifiers might expect /A?enriched to be semantically closer to /A than /B, but the machines don't make that assumption.
It's perfectly reasonable for /A?enriched to produce representations using a different schema, or even a different content-type (as far as the HTTP application is concerned, it's perfectly reasonable that /A be an HTML document and /A?enriched be an image).
Because the machines don't care, you've got additional degrees of freedom in how you design both you resources and your resource identifiers, which you can use to enjoy additional benefits, including designing a model that's easy to implement, or easy to document, or easy to interface with, or easy to monitor, or ....
Design is what we do to get more of what we want than we would get by just doing it.

How to Automate a XACML String Manipulation Function in ALFA?

We got a request to write a set of rules in a policy which should generate a detailed log message, both for Permit and Deny condition. The resulting log output is a construction of several attributes, or transferred from the XACML request input, or from the PIP Java routines, where we get additional attributes like UTC log event time and the service status of the data sources, among a set of attributes from the database. All information should be transported to the PEP by means of XACML obligations, which converts the String into a final database logging step.
Is there a way to create a reusable function in ALFA language that groups all required String manipulation statements in a callable manner, in a similar way to Java programmatic function, avoiding a writing of redundant code sections.
No there isn't a way in the current version of ALFA to define a custom function that would group all that you are interested in.
However, you could very well define a rule that contains the advice / obligation with all the logic and then reference the rule in all the places you need it. In ALFA, you can reference Rule elements (something that is not possible in XML/XACML)
Here is an example:
namespace so{
import Attributes.*
attribute messageContent{
category = environmentCat
id = "messageContent"
type = string
}
obligation message = "message"
/**
* Reusable rule with obligation pattern
*/
rule giveReason{
deny
on deny {
obligation message{
subjectId = subjectId
currentDateTime = currentDateTime
messageContent = "Hi, "+stringOneAndOnly(subjectId)+
". You cannot do action "+
stringOneAndOnly(Attributes.actionId)+
" on "+stringOneAndOnly(resourceId)+
" at "+stringFromDateTime(dateTimeOneAndOnly(currentDateTime))+"."
}
}
}
/**
* Your policies
*/
policyset somePS{
apply firstApplicable
policy example1{
apply firstApplicable
/**
* Other rules go here
*/
giveReason // link to common rule
}
policy example2{
apply firstApplicable
/**
* Other rules go here
*/
giveReason // link to common rule
}
}
}

In XACML and ALFA, how can I achieve a layered set of policies that check environment attributes?

I want to write a layered policy whereby the first layer will always check the environment such as:
checking the user has a valid IP-address,
checking the time is within a valid time frame and day of the week
the user's device is a valid device
The lower layers will take care of the actual requested actions e.g. add, view, update, delete on a certain set of resources such as medical records, insurance data, bank accounts...
In plain English, the rules look like the following
Policy that permits if all environment rules return permit
Rule1: Only allow users with an IP-address that is in the range of [bag with ip-address ranges]
Rule2: Only allow requests for actions from monday to friday
Rule3: Only allow requests for actions from 7:00 AM to 22:00 PM
Rule4: Only allow requests for actions from a Desktop or a laptop
How can this be done using ALFA, the Axiomatics Language for Authorization?
This is a good question and there are several good ways of doing it. One example would be to rewrite the logic and express the following:
PolicySet with a combining algorithm of first-applicable
deny if time is wrong
deny if device is invalid
deny if IP is not in valid range
set of possible actions and resources-based policies yielding a Permit.
This is what it looks like in ALFA:
namespace com.axiomatics.example{
policyset global{
apply firstApplicable
policy securityChecks{
apply firstApplicable
rule denyOutsideOfficeHours{
deny
}
rule denyInvalidDevice{
deny
}
rule denyInvalidIP{
deny
}
}
policyset myBusinessPolicies{
apply firstApplicable
/**
* Add your business policies here
*/
}
}
}
This is merely the scaffolding. Let's now look at the attributes we need:
the current time
the user's current IP
the user's device type
We will not worry about how we obtained these values. It is up to the Policy Enforcement Point or Policy Information Point to worry about that.
The first rule will use the currentTime attribute. It is a default attribute in ALFA and is defined as follows:
attribute currentTime {
id = "urn:oasis:names:tc:xacml:1.0:environment:current-time"
type = time
category = environmentCat
}
The updated rule now looks like the following:
rule denyOutsideOfficeHours{
target clause currentTime<"09:00:00":time or currentTime>"17:00:00":time
deny
}
In this example we use static lower and upper limits (9am and 5pm respectively) but these could also be attributes in which case we'd have to use a condition rather than a target. Note the ALFA notation used to convert the string value into the relevant datatype: "17:00:00":time.
The second rule looks as follows:
rule denyInvalidDevice{
condition not(stringIsIn(stringOneAndOnly(deviceType), stringBag("laptop","desktop")))
deny
}
In this rule, we have to use a condition because it is impossible to express a negative constraint in a target. The condition checks that there is an attribute called deviceType and that it contains a single value, no more and no less. That value must not be equal to either laptop or desktop in order for the deny to kick in. By the way, string comparison in XACML is case-sensitive by default.
The last rule is similar and again we have to use a condition to negate the test. Here we use the ipAddressRegexpMAtch XACML function to check whether the user's IP (subjectLocalityIpAddress) matches a given IP address pattern.
rule denyInvalidIP{
condition not(
ipAddressRegexpMatch(
"^(10)\\.(10)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])\\:([80|443])$",
ipAddressOneAndOnly(subjectLocalityIpAddress)
)
)
deny
}
Note that the the backslash had to be escaped with another backslash. This is due to the ALFA syntax. The XACML policy itself, once converted to XML, will not contain 2 backslash characters.
The resulting policy all combined together is the following:
namespace com.axiomatics.example{
import Attributes.*
attribute deviceType{
category = subjectCat
id = "deviceType"
type = string
}
attribute userIP{
category = subjectCat
id = "deviceType"
type = string
}
policyset global{
apply firstApplicable
policy securityChecks{
apply firstApplicable
rule denyOutsideOfficeHours{
target clause currentTime<"09:00:00":time or currentTime>"17:00:00":time
deny
}
rule denyInvalidDevice{
condition not(stringIsIn(stringOneAndOnly(deviceType), stringBag("laptop","desktop")))
deny
}
rule denyInvalidIP{
condition not(
ipAddressRegexpMatch(
"^(10)\\.(10)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])\\:([80|443])$",
ipAddressOneAndOnly(subjectLocalityIpAddress)
)
)
deny
}
}
policyset myBusinessPolicies{
apply firstApplicable
/**
* Add your business policies here
*/
}
}
}
I hope this helps. Send us your questions via Stackoverflow or via our Developer's Blog.

How to update a XACML / ALFA policy?

I have written policy in ALFA where:
if the amount to transfer is greater than the transfer limit, then the request should be denied.
I wanted to know how to specify a particular transfer limit. And from an administrator point of view, if in future i want to update the transfer limit, where and how should it be done?
For eg .I want to set current transfer limit to $2000. How do I do that and then how do I update the transfer limit, if I want to?
To add to what David mentioned, you could set this value in a database cell and update its value offline of ABA/XACML (using other processes in place in your org.). The value can then be queried at evaluation time by telling your PDP that withdrawalLimit is queried from a specific DB using the SQL "select limit from ...."
So, that is the advantage of XACML, As rules are defined in a policy, you can update the access control rules in dynamic manner. Transfer limit may have been configured in your XACML policy. You can update it using the by editing the XACML policy. Then this update must be eserveredffected for the PDP runtime and request would be severed according to it.
ALFA plugin would have easy way of updating the XACML policy attributes rather than just updating the raw policy. Hope you may find it. But if you update the XACML policy, it would also work.
It's good to see you are making progress. In your case, the authorization policy in ALFA would look as follows:
namespace com.axiomatics.banking{
attribute actionId{
category = actionCat
id = "actionId"
type = string
}
attribute resourceType{
category = resourceCat
id = "resourceType"
type = string
}
attribute amount{
category = resourceCat
id = "amount"
type = double
}
/**
* Policy to transfer money
*/
policy transferMoney{
target clause actionId=="transfer" and resourceType=="money"
apply firstApplicable
/**
* Deny access if amount is greater than 2000
*/
rule checkAmount{
target clause amount > 2000
deny
}
/**
* Grant access
*/
rule allow{
permit
}
}
}
Note that in my example I use a negative rule to deny access. This is great, for instance, if I want to add Advice or Obligation to that rule to indicate the reason for denial.
Now your question doesn't relate so much to the policy structure but rather to the values of the attributes. In XACML you have two options. Either:
you "hard-code" the value into the policy, or
you externalize the value and put it inside a policy information point (PIP) which could be a database, a web service, an LDAP... The benefit of externalizing the value is that you can now update the value without having to change the policy. The policy becomes more generic. Also it means you can have user-specific limits.
In the latter case, your rule becomes:
/**
* Deny access if amount is greater than the user's withdrawal limit
*/
rule checkAmount{
condition amount > withdrawalLimit
deny
}
In the Axiomatics Policy Server, you can configure a PIP / attribute connector to retrieve the value based on, say, the user id.
HTH,
David.