+

Obligations and Advice in XACML part 2

In a previous blog post ​we discussed the use of XACML obligations and advice. I concluded the post with the cliff hanger:

An interesting use of advice is as a means to tell the PEP the reasons why a request has been denied; but to show you how this is done I would need to introduce you to the way the PDP calculates the advice for a decision.

So let’s start then by taking a look at the way the PDP calculates the obligations (or advice) that correspond to a decision.

The XACML specification tells us how it is done (§​7.18)​:

“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.”

Right… let’s try and make sense of that.

First, let’s see how “advice expressions” are turned into “advice”. The difference between an advice expression and advice is that the arguments of the former are expressions, and the arguments of the latter are values. So, if we have an advice expression

advice notifyDoctor { notificationRecipient = doctorId }

where d​octorId​ is a string attribute with the value “doc42”, the advice expression will evaluate to

advice notifyDoctor { notificationRecipient = "doc42" }

Of course the expressions used as arguments can be complex

advice notifyDoctor {
    notificationRecipient = stringConcatenate(
                                stringOneAndOnly(hospitalId),
                                stringConcatenate(":",stringOneAndOnly(doctorId)))
}

This advice expression, in the same context as before and with h​ospitalId ​having the value “krlk”, would evaluate to

advice notifyDoctor { notificationRecipient = "krlk:doc42" }

Notice that if the evaluation of any of the argument expressions results in Indeterminate​then the evaluation of the whole advice expression will result in Indeterminate. ​For example, evaluating

advice notifyDoctor {
  notificationRecipient = doctorId
  copies = 1/0
}

will always result in I​ndeterminate.​

Now, how do we calculate the advice for a rule?

First we check that the rule would actually return a decision, that is to say it would return what we call its “effect”: P​ermit​ or D​eny ​(but not N​otApplicable​ or I​ndeterminate)​. Then we pick all the advice expressions with AppliesTo​equal to the effect, and we evaluate them into the corresponding advice. If any of these advice expressions evaluates to Indeterminate, ​the w​hole rule ​evaluates to Indeterminate.​Otherwise, the rule evaluates to its effect, accompanied by the evaluated advice.

Next, how do we calculate the advice for a policy?

This is a bit more complicated. Whenever we evaluate a rule in the policy, we collect the resulting advice into two groups: the advice that applies on P​ermit​ and the advice that applies on D​eny.​Once we reach a point in which we are ready to return a decision for the policy that is neither NotApplicable​nor Indeterminate​we proceed and evaluate all the policy’s own ​advice expressions that apply to the decision. If neither of these evaluates to I​ndeterminate,​ we return the decision, accompanied by the advice just calculated p​lus ​the advice we have collected in the group that corresponds to the decision. If any of these evaluates to I​ndeterminate​ the w​hole policy evaluates to I​ndeterminate.​

Now, for the last bit, how do we calculate the advice for a policy set?

We do it in a similar way as we do it for policies. Whenever we evaluate a policy in the policy set, we collect the resulting advice into two groups: the advice that applies on Permit​and the advice that applies on D​eny. ​And again, once we reach the point where we are ready to return a decision for the policy set (that is neither N​otApplicable ​nor Indeterminate)​we proceed and evaluate all the policy set’s own​ advice expressions that apply to the decision. If neither of these evaluates to I​ndeterminate​ we return the decision, accompanied by the advice just calculated plus ​the advice we have collected in the group that corresponds to the decision. If any of these evaluates to I​ndeterminate the w​hole policy set​evaluates to I​ndeterminate.​

Now that we know all this, let’s see how advice can be used as a means to tell the PEP the reasons why a request has been denied.

Consider the following policy:

policyset Root {
    apply denyOverrides
    policy A {
        apply permitOverrides
        rule A1 {
            deny
            on permit { advice dummy  { message = “a7” }}
            on deny   { advice reason { message = “a8" }}
        }

        rule A2 {
            permit
            on permit { advice dummy  { message = “a9” }}
            on deny   { advice reason { message = “a10" }}
        }
        on permit { advice dummy  { message = “a3” }}
        on deny   { advice reason { message = “a4" }}
    }
    policy B {
        apply denyOverrides
        rule B1 {
            permit
            on permit { advice dummy  { message = “a9” }}
            on deny   { advice reason { message = “a10" }}
        }
        rule B2 {
            deny
            on permit { advice dummy  { message = “a7” }}
            on deny   { advice reason { message = “a8" }}
        }
        rule B3 {
            deny
            on permit { advice dummy  { message = “a9” }}
            on deny   { advice reason { message = “a10" }}
        }
        on permit { advice dummy  { message = “a5” }}
        on deny   { advice reason { message = “a6" }}
    }
    on permit { advice dummy  { message = “a1” }}
    on deny   { advice reason { message = “a2" }}
}

This policy evaluates the same for all decision requests. An evaluation of this policy looks like this:

The resulting decision carries a set of advice that tells us that the decision is ​Deny because “a14” (Rule B2 denied), “a6” (Policy B denied) and “a2” (Root policy set denied).

Although interesting in its own right, this technique cannot be used reliably with all policies, because the advice you will get may not really be a good “reason” for the decision. It depends a lot on how you structure your policies and which combining algorithms you use.

For example, imagine a policy that uses the on Permit Apply Second ​combining algorithm​.

 

AThe diagram shows two possible evaluations of a simple policy that combines three rules with on Permit Apply Second.​

Notice that ​advice 1 ​is returned only in one case, although I would argue that the fact that the first policy is a D​eny​ is part of the reason why the whole policy set evaluates to Deny.​

One can think of ways to work around issues like this, but the resulting policies will be more error-prone and more difficult to maintain. A better, more reliable way to analyze your policies is to use a specialized tool like the Axiomatics Policy Auditor or Axiomatics Reverse Query.​

I hope this post has shed some more light on the topic of obligations and advice in XACML. Thank you for staying with me all the way!

Related Articles

Meeting today’s dynamic authorization and access challenges: The Axiomatics story | Dynamically Speaking
Dynamically Speaking
For more than 15 years, Axiomatics has worked with companies worldwide to define and deliver solutions to the most complex authorization and access challenge. In...
Getting started with Zero Trust using dynamic authorization | Dynamically Speaking
Dynamically Speaking
Zero Trust. It’s everywhere. It’s a methodology that’s been around for years, and we are now seeing a significant uptick in the number of enterprises...
The case for dynamic authorization in banking and finance
Attribute Based Access Control (ABAC)
More than other organizations, banks, and financial institutions face the highest levels of scrutiny when it comes to how they protect critical assets and sensitive...