The authorization decision, applicable to a particular request, may be composed of several individual rules or policies. For instance, a door access system wants to provide access to a door based on a user's identity, but also have the ability to override the access in case of a building-wide lockdown being put in place. To express such a policy in ALFA, we need to provide a combining algorithm, for these two rules, that favors deny over permit, namely: denyOverrides.
namespace AcmeCorp
{
import Oasis.Attributes
policy buildingAccess
{
// Algorithm for how to produce the policy outcome
apply denyOverrides
target clause ResourceType == "door"
rule openMainDoor { ... }
rule EnforceLockdown { ... }
}
}
ALFA mandates that policies and policy sets must contain a combining algorithm, as they can contain multiple rules and polices. Enforcer has the following combining algorithms:
When the PEP requests the PDP to evaluate a policy, it can return one of the following:
- permit
- deny
- not applicable
- indeterminate
Internally there are, in fact, two additional results that are possible:
- indeterminate permit
- indeterminate deny
As a consumer of the PDP or PEP, you will never encounter these final two, but the combining algorithms will, and potentially use them as part of their combining strategy. The PDP generates indeterminate results when a rule fails to evaluate completely. In this case, if the failing rule's desired outcome is permit, then it returns indeterminate permit, if its desired outcome was deny then indeterminate deny. If a combining algorithm tries to combine both an indeterminate permit and an indeterminate deny, it will often combine them into an indeterminate outcome.
First Applicable (firstApplicable)
First Applicable is, possibly, the most straightforward combining algorithm. It returns the outcome from the first evaluated outcome that does not produce not applicable. If there are none, then the output from the combining algorithm is not applicable.
This combining algorithm is useful when combining the outcome of many policies when only one in the set will apply to the request. For example, the finance policy will likely handle the authorization decision for the finance system, and not the buildingAccess or hospital policies.
It is worth stating that the combining algorithms will only evaluate policies if they need to. For example if the finance policy produces a not applicable and the buildingAccess produces a permit, then only the finance and buildingAccess policy would have been evaluated.
namespace AcmeCorp
{
policyset global
{
apply firstApplicable
policy finance
policy buildingAccess
policy hospital
}
}
Permit Unless Deny (permitUnlessDeny)
With Permit Unless Deny, if any of the contained outcomes evaluate to deny, then deny is the final outcome. For any other outcome (any form of indeterminate, not applicable or permit) the result is permit. Permit Unless Deny is useful for situations where it's more convenient to describe what needs to be denied instead of permitted.
namespace AcmeCorp
{
policyset global
{
apply permitUnlessDeny
policy restrictedAreaA
policy restrictedAreaB
policy restrictedAreaC
}
}
This combining algorithm is also useful in that it keeps the PEP logic simple; the PEP either receives a permit or deny. Configuring PEP bias to permit would have similar behavior but affects all policy evaluations.
Deny Unless Permit (denyUnlessPermit)
Deny Unless Permit is the inverse of the previous algorithm. If any of the contained outcomes evaluate to permit, then permit is the final outcome. For any other outcome the result is deny
Deny Unless Permit is useful for situations where it's more convenient to describe what is permitted.
namespace AcmeCorp
{
policyset global
{
apply denyUnlessPermit
policy buildingAccess
policy workingWeek
}
}
This combining algorithm is also useful in that it keeps the PEP logic simple, as it either receives a permit or deny. Configuring PEP bias to deny would have similar behavior, but, again, would affect all policy evaluations.
Deny Overrides (denyOverrides)
The Deny Overrides combining algorithm will consider the various forms of indeterminate when making a decision.
- If any decision is deny the result is deny
- Otherwise, if any decision is indeterminate, the result is indeterminate
- Otherwise, if any decision is Indeterminate deny and another decision is indeterminate permit or Permit, the result is indeterminate
- Otherwise, if any decision is indeterminate deny, the result is indeterminate deny
- Otherwise, if any decision is permit, the result is permit
- Otherwise, if any decision is indeterminate permit, the result is indeterminate permit
- Otherwise, the result is not applicable
For example, the buildingAccess policy allows authorized personal into the building. To prevent employees from gaining access out of hours, a workingWeek policy could be applied. So, while for an employee the buildingAccess policy would emit permit, the workingWeek policy would prevent access out of hours by issuing a deny.
namespace AcmeCorp
{
policyset employeeAccess
{
apply denyOverrides
policy buildingAccess
policy workingWeek
}
}
To summarise: if a possible deny outcome failed to evaluate, then, even though there may be a permit outcome, the permit won't propagate. This is handled by step 3 & 4 above.
Permit Overrides (permitOverrides)
Permit Overrides is the inverse of Deny Overrides.
- If any decision is permit, the result is permit
- Otherwise, if any decision is indeterminate, the result is indeterminate
- Otherwise, if any decision is indeterminate permit and another decision is indeterminate deny or deny, the result is indeterminate
- Otherwise, if any decision is indeterminate permit, the result is indeterminate permit
- Otherwise, if any decision is deny, the result is deny
- Otherwise, if any decision is indeterminate, deny the result is indeterminate deny
- Otherwise, the result is not applicable.
For example, in general, a doctor may only be able to access their own patients’ medical records. However, in cases of emergency, another doctor may be able to request the records by declaring an emergency reason, and for the PEP to audit the fact via an obligation.
namespace AcmeCorp
{
policyset medicalRecords
{
apply permitOverrides
policy accessPatientRecords
policy emergencyAccessToPatientRecords
}
}
To summarise if a possible permit outcome failed to evaluate, then even though there may be a deny outcome, the deny won't propagate. This is handled by steps 3 & 4 above.