Skip to main content

Data Filtering with OPA

Data Filtering is a common use case for authorization that goes beyond "allow or deny?". It is often related to searching (or listing) multiple entities. This page starts with a problem exposition before going into the details of data filtering with OPA in the next sections.

Authorization evaluation questions ask "Can subject do action to resource (with context)?", e.g.

  • Can Sally (subject) withdraw (action) $5,000 (context) from account 058201 (resource)?

The response to this is allow or deny.

Authorization search questions ask which values of an unknown generate an allow or deny decision, e.g.:

  • Unknown Actions: What actions can Javier do on an escalated ticket?
  • Unknown Context: During what hours can badge #2541 access the store room?
  • Unknown Subject: Who is allowed to approve payments over $10,000?
  • Unknown Resource: Whose salaries can a Director see?

The response to this is a set of filtered application data.

A quick example

Consider an employees database table with salary information. The question is: whose salaries can a Director see?

The rule is: Directors may see the salaries of employees in their own department. When Alice (Engineering Director) lists employees, she should see rows 1-3 (the Engineering employees):

idnamedepartmentrolesalary
1Aliceengineeringdirector130000
2Bobengineeringengineer90000
3Carolengineeringengineer85000
4Davemarketingdirector120000
5Evemarketingmanager95000

OPA can be used to derive the needed SQL filter at run time, leveraging OPA's partial evaluation feature.

1. Input passed to OPA

Alice is a Director of the Engineering department. The application sends her user context to OPA:

input.json
{
"user": {
"name": "Alice",
"role": "director",
"department": "engineering"
}
}

2. OPA evaluates the policy

policy.rego
# METADATA
# scope: package
# compile:
# unknowns: [input.employees]
package filters

include if {
input.user.role == "director" # known: true for Alice, consumed
input.employees.department == input.user.department # unknown == known → SQL condition
}

OPA partially evaluates this policy and constructs the SQL condition as follows:

  • The value of input.employees.department is unknown during partial policy evaluation — it refers to a table column in the database.
  • The value of input.user.department is known during partial policy evaluation — it resolves to the value "engineering" from the input document.

3. OPA returns a SQL filter

SQL filter for Alice
WHERE employees.department = 'engineering'

4. Application Runs Query

The application can then query the database using this filter and process or display the returned data.

For a hands-on walkthrough, see the SQL Data Filtering Tutorial.