ALFA Language Basics

ALFA is a constrained, highly-structured fine-grained authorization policy language. Let's unpack each term.

  • Constrained: ALFA is purpose-built for authorization. As such it is not a full-blown programming language, unlike Open Policy Agent's Rego. This makes it easier to read, write, test, and audit.
  • Highly-structured: unlike Cedar and Rego, ALFA provides built-in structure or scaffolding. A policy is in fact made up of one of three elements:
    • PolicySet: the PolicySet (PS) is generally the root element. It can contain other PolicySet elements as well as Policy elements. It can be referenced or inlined.
    • Policy: the Policy generally lives inside a PolicySet element. It can be referenced or inlined. A Policy contains Rule elements.
    • Rule: the Rule is the lowest type of structure. It contains the effect (Permit or Deny).
  • Fine-grained: With ALFA, you can implement authorization policies that are as broad or as specific as you see fit. You can express use cases such as A manager can view records in their department or Alice can view photo album 'Croatia 2014'.
  • High-performant: ALFA is built for speed. Because it is constrained and highly-structured, the evaluation engine can quickly prune all the unneeded policies and only focus on the relevant ones.
  • Built-in conflict resolution: ALFA lets you control how policies are combined and how conflicts are handled. The engine will always guarantee the same consistent result. You have oversight over priorities.
  • Native support for ABAC and ReBAC: ALFA is all about attributes. They can describe the user, the action, the object, contextual data, and relationships. You can define your own attributes and choose where to source the data from.

Structure

PolicySet

A PolicySet is the topmost structural element in an ALFA policy. It can contain PolicySet and Policy elements. A PolicySet contains a Target to scope access. Use PolicySet elements to organize your policies into logical building blocks e.g. use cases, business applications, and features.

Policy

A Policy is the second structural element in an ALFA policy. It can contain Rule elements only. A Policy contains a Target to scope access. Use Policy elements to organize your rules into logical building blocks e.g. use cases, business applications, and features.

Rule

A Rule is the third and last structural element in an ALFA policy. It contains the effect of the overall policy i.e. either Permit or Deny. A Rule contains a Target to scope access. It can also contain a Condition Use Rule elements to define the actual permissions you want to grant or deny.

Cheatsheet

Name Description Children Target Condition Obligation & Advice
PolicySet Topmost element of an ALFA policy.
  • PolicySet
  • Policy
Policy Intermediary element of an ALFA policy.
  • Rule
Rule Leaf element of an ALFA policy. It contains the effect, either Permit or Deny.
  • Permit
  • Deny

Targets & Conditions

Target

A Target is a simple way to match an incoming authorization request with a policy. In a target, you can compare an attribute to a value e.g. role=="manager". You can also use and and or to combine attribute comparisons e.g. role=="manager" and action=="view" and object=="financial record". Of all the functions available in ALFA, only those that compare an attribute to a value (e.g. string equality) can be used in a Target. For a complete list of functions, check out the ALFA Function Reference.

When to use Targets?

Use Target for simple matching or scoping. Break down your authorization challenge into simple statements you can then use in your Target.

Condition

A Condition is a more advanced way to match an incoming authorization request with a policy. You are free to use any of the functions available in ALFA in any structure you see fit. You can nest as many functions as you like. Conditions are particularly useful to implement relationships. If for instance, you want to grant a user access to a record because they are in the same department or because the user's clearance is greater than the record's classification, then you use a Condition.

  • user.clearance>record.classification // Permit if the user's clearance is high enough
  • user.department==record.department // Permit if the user is in the same department as the record

When to use Conditions?

Use Condition for advanced logic, attribute manipulation, or relationships.

Tip

Try to use Target elements as much as you can to organize your policies. Only use Condition when you need advanced logic or ReBAC (relationships).

Conflict Resolution & Combining Algorithms

Built-in conflict resolution

One of the coolest features of ALFA is its ability to organize, stack up, mix, and match policies. It means you can have a policy that will grant managers access to records and another that will deny access outside office hours.

Now, of course, if you have such policies, you need to decide which one wins. That's why ALFA comes with built-in conflict resolution. The mechanism used to handle conflicts is called a combining algorithm. It is defined at the level of the PolicySet or Policy parent element and it applies to that element's children.

ALFA Combining Algorithms Definitions

  • denyOverrides:any of the children returns Deny, then evaluation is stopped and Deny is returned.View Truth Table.
  • permitOverrides:any of the children returns Permit, then evaluation is stopped and Permit is returned.View Truth Table.
  • firstApplicable:as soon as a child returns either of Permit or Deny, then evaluation is stopped and that decision is returned.View Truth Table.
  • orderedDenyOverrides:same as denyOverrides. Order is strictly enforced.View Truth Table.
  • orderedPermitOverrides:same as permitOverrides. Order is strictly enforced.View Truth Table.
  • denyUnlessPermit:any of the children returns Permit, then evaluation is stopped and Permit is returned. Otherwise, Deny is returned.View Truth Table.
  • permitUnlessDeny:any of the children returns Deny, then evaluation is stopped and Deny is returned. Otherwise, Permit is returned.View Truth Table.
  • onlyOneApplicable:only one of the children must apply and return a decision. That decision is the overall decision, either Permit or Deny.View Truth Table.
  • onPermitApplySecond:the decision coming from the first child is Permit, then return the decision from the second child, otherwise return the decision from the third child (if any).View Truth Table.

Example

A diagram depicting how ALFA handles conflict resolution via combining algorithms

In the example above, we have a Policy which contains three Rule children. Each rule returns its own decision: Permit, Deny, and NotApplicable respectively. Depending on the combining algorithm defined on the level of the policy, the end result will either be Permit, Deny, or Indeterminate.

  • denyOverrides: Deny.
  • permitOverrides: Permit.
  • firstApplicable: Permit.
  • orderedDenyOverrides: Deny.
  • orderedPermitOverrides: Permit.
  • denyUnlessPermit: Permit.
  • permitUnlessDeny: Deny.
  • onlyOneApplicable: Indeterminate.
  • onPermitApplySecond: Deny.

ALFA Combining Algorithm Truth Tables

DenyOverrides 1. First choose the column below
Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
2. Then choose the row Permit Permit Deny Permit Indeterminate (D) Permit Indeterminate (DP)
Deny Deny Deny Deny Deny Deny Deny
NotApplicable Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
Indeterminate (D) Indeterminate (D) Deny Indeterminate (D) Indeterminate (D) Indeterminate Indeterminate (DP)
Indeterminate (P) Permit Deny Indeterminate (P) Indeterminate (DP) Indeterminate (P) Indeterminate (DP)
Indeterminate (DP) Indeterminate (DP) Deny Indeterminate (DP) Indeterminate (DP) Indeterminate (DP) Indeterminate (DP)
PermitOverrides 1. First choose the column below
Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
2. Then choose the row Permit Permit Permit Permit Permit Permit Permit
Deny Permit Deny Deny Deny Indeterminate (P) Indeterminate (DP)
NotApplicable Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
Indeterminate(D) Permit Deny Indeterminate (D) Indeterminate (D) Indeterminate (DP) Indeterminate (DP)
Indeterminate (P) Permit Indeterminate (P) Indeterminate (P) Indeterminate (DP) Indeterminate (P) Indeterminate (DP)
Indeterminate (DP) Permit Indeterminate (DP) Indeterminate (DP) Indeterminate (DP) Indeterminate (DP) Indeterminate (DP)
denyUnlessPermit 1. First choose the column below
Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
2. Then choose the row Permit Permit Permit Permit Permit Permit Permit
Deny Permit Deny Deny Deny Deny Deny
NotApplicable Permit Deny Deny Deny Deny Deny
Indeterminate (D) Permit Deny Deny Deny Deny Deny
Indeterminate (P) Permit Deny Deny Deny Deny Deny
Indeterminate (DP) Permit Deny Deny Deny Deny Deny
PermitUnlessDeny 1. First choose the column below
Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
2. Then choose the row Permit Permit Deny Permit Permit Permit Permit
Deny Deny Deny Deny Deny Deny Deny
NotApplicable Permit Deny Permit Permit Permit Permit
Indeterminate (D) Permit Deny Permit Permit Permit Permit
Indeterminate (P) Permit Deny Permit Permit Permit Permit
Indeterminate (DP) Permit Deny Permit Permit Permit Permit
firstApplicable 1. First choose the column below
Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
2. Then choose the row Permit Permit Deny Permit Indeterminate (D) Indeterminate (P) Indeterminate (DP)
Deny Permit Deny Deny Indeterminate (D) Indeterminate (P) Indeterminate (DP)
NotApplicable Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
Indeterminate (D) Permit Deny Indeterminate (D) Indeterminate (D) Indeterminate (P) Indeterminate (DP)
Indeterminate (P) Permit Deny Indeterminate (P) Indeterminate (D) Indeterminate (P) Indeterminate (DP)
Indeterminate (DP) Permit Deny Indeterminate (DP) Indeterminate (D) Indeterminate (P) Indeterminate (DP)
orderedDenyOverrides 1. First choose the column below
Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
2. Then choose the row Permit Permit Deny Permit Indeterminate Permit
Deny Deny Deny Deny Deny Deny Deny
NotApplicable Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
Indeterminate (D) Indeterminate Deny Indeterminate (D) Indeterminate (D) Indeterminate (D) Indeterminate (DP)
Indeterminate (P) Permit Deny Indeterminate (P) Indeterminate (D) Indeterminate (P) Indeterminate (DP)
Indeterminate (DP) Indeterminate (DP) Deny Indeterminate (DP) Indeterminate (D) Indeterminate (D) Indeterminate (DP)
orderedPermitOverrides 1. First choose the column below
Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
2. Then choose the row Permit Permit Permit Permit Permit Permit Permit
Deny Permit Deny Deny Deny Indeterminate (P) Indeterminate (DP)
NotApplicable Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
Indeterminate(D) Permit Deny Indeterminate (D) Indeterminate (D) Indeterminate (DP) Indeterminate (DP)
Indeterminate (P) Permit Indeterminate (P) Indeterminate (P) Indeterminate (DP) Indeterminate (P) Indeterminate (DP)
Indeterminate (DP) Permit Indeterminate (DP) Indeterminate (DP) Indeterminate (DP) Indeterminate (DP) Indeterminate (DP)
onlyOneApplicable 1. First choose the column below
Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
2. Then choose the row Permit Indeterminate Indeterminate Permit Indeterminate (D) Indeterminate (P) Indeterminate (DP)
Deny Indeterminate Indeterminate Deny Indeterminate (D) Indeterminate (P) Indeterminate (DP)
NotApplicable Permit Deny NotApplicable Indeterminate (D) Indeterminate (P) Indeterminate (DP)
Indeterminate (D) Indeterminate (D) Indeterminate (D) Indeterminate (D) Indeterminate (D) Indeterminate (DP) Indeterminate (DP)
Indeterminate (P) Indeterminate (P) Indeterminate (P) Indeterminate (P) Indeterminate (DP) Indeterminate (P) Indeterminate (DP)
Indeterminate (DP) Indeterminate (DP) Indeterminate (DP) Indeterminate (DP) Indeterminate (DP) Indeterminate (DP) Indeterminate (DP)