Evaluation engines
Evaluation engines are used to implement checks for AccessPolicy rules
Aidbox provides several ways to specify rules for AccessPolicy
resources — so called evaluation engines. They come with their own syntax and offer varying degrees of flexibility and convenience for writing those rules.
There are five main engines. They are used to specify rules for a generic request object.
Allow
JSON Schmea
SQL
Matcho
Complex
There are also two additional engines which serve as a convenient way to write rules specifically for RPC endpoints.
Allow-RPC
Matcho-RPC
All of them are described in a greater detail below.
Allow
allow
engine always evaluates to true
regardless of a request object. Use it if you want to provide an unrestricted access to everything.
Example
JSON Schema
json-schema
engine allows you to use JSON Schema to validate the request object. It is specified under schema
field of AccessPolicy
resource. Currently supported JSON Schema version is draft-07.
Fields with empty values — []
, {}
, ""
, null
— are removed from request before before access policy checks are applied to it. Make sure to specify all necessary fields as required.
Example
The following policy requires request.params.resource/type
to be present and have a value of "Organization"
:
SQL
sql
engine executes an SQL statement and uses its return value as an evaluation result. Thus the statement should return a single row with just one column:
SQL statement can refer to request fields with a double curly braces interpolation. String inside the braces will be used as a path to value in the request object.
Example
Suppose that we are checking a request that comes with a User
resource referencing a Practitioner
through User.data.practitioner_id
element. The following policy allows requests only to /fhir/Patient/<patient_id>
URLs and only to those patients who have a Patient.generalPractitioner
element referencing the same practitioner as a User
of our current request. In other words, User
as a Practitioner
is only allowed to see his own patients — those who reference him as their generalPractitioner
.
Interpolation Rules
You can parameterize your SQL queries with request object using {{path}}
syntax. For example, to get a user role provided at {user: {data: {role: "admin"}}}
you write {{user.data.role}}
. Parameter expressions are escaped by default to protect from SQL injection.
For dynamic queries — to parameterize table name, for example — you have to use {{!path}}
syntax. The expression SELECT true from {{!params.resource/type}} limit 1
when a request contains {params: {"resource/type": "Patient"}}
will be transformed into SELECT true from "patient".
By default identifier names are double quoted and lower-cased.
Matcho
matcho
engine leverages Matcho pattern matching — custom DSL developed by Health Samurai. It has very compact and declarative syntax with a limited expressivity. It is well-suited for writing all sorts of rules and thus is one of the easiest options to specify AccessPolicy
checks.
Match DSL definition:
If pattern is a dictionary, search for its inclusion into a test subject. This algorithm is nested and recursive. Pattern
{x: 1}
matches{x: 1, y: 2, …}
``Pattern{a: {b: 5}
matches{a: {b: 5, c: 6, …}, d: 7, …}
If a pattern is an array, search for its elements in the order given. Pattern
[1, 2]
matches[1, 2, 3, …]
Primitive values — strings, numbers and booleans — are compared by value.
If a string starts with
#
, it is treated as a regular expression. Pattern{a: "#\\d+"}
matches{a: "2345"}
If a string starts with
.
, it is interpreted as a path in the current test subject. Pattern{params: {user_id: ".user.id"}}
matches{user: {id: 1}, params: {user_id: 1}}
whereuser.id == param.user_id
.Special string literals (postfixed with
?)
present? — matches non-
null
values; Pattern{a: "present?"}
matches{a: 5}
or{a: {b: 6}}
nil? — matches
null
values;not-blank? — matches non-empty string.
Special keys:
$enum — value must be equal to one of the items in the enumeration. Pattern
{request-method: {$enum: ["get", "post"]}}
matches{request-method: "post"}
$one-of — value must match any of the patterns. Pattern
{a: {$one-of: [{b: "present?"}, {c: "present?"}]}
matches{a: {c: 5}}
$reference — parse
Reference
or string into aidbox format. Examples:Parse
Reference
elementsparser: {reference: "Patient/pid"} => {id: "pid", resourceType: "Patient"}
{resource: {patient: {$reference: {id: '.user.data.patient_id'}}}
Parse reference string
"Patient/pid" => {id: "pid", resourceType: "Patient"}
{params: {subject: {$reference: {id: '.user.data.patient_id'}}}
$contains — collection must contain at least one match. Pattern
{type: {$contains: {system: "loinc"}}
matches{type: [{system: "snomed"}, {system: "loinc"}]}
$every — each item in a collection must satisfy a pattern. Pattern
{col: {"$every": {foo: "bar"}}
matches{col: [{foo: "bar"}, {foo: "bar", baz: "quux"}]}
$not — negates a pattern. Pattern
{message: {$not: {status: private}}
matches {message:{status: public}}
and does not match{message: {status: private}}
. Be careful using$not
as it is possible to create too permissive policies.
Consider the following policy which uses $not
key.
While original intent was to forbid guest
users to delete Patient
resources this AccessPolicy
allows to do DELETE /Patient/<id>
for all the other users including unauthorized ones. In this case it is better to explicitly list allowed roles with $enum.
More examples
Need help with matcho
engine? Contact us on the telegram chat!
Complex
complex
engine allows you to combine several rules with and
and or
operators. You can use any engine rule to define a rule and even complex
engine itself but it is forbidden to have both and
and or
keys on the same level. Rules are defined as an array of objects which must include an engine with a set of corresponding keys.
Example
Policy in the example above represents the following logical expression:
check-1 AND (check-2 OR check-3)
Example
Let's split SQL policy example from above into two separate rules and combine them under and
rule:
Allow-RPC
Requires to specify type: rpc
for AccessPolicy
resource.
allow-rpc
engine allows access to every RPC endpoint listed under the rpc
field of the AccessPolicy
resource.
Example:
Matcho-RPC
Requires to specify type: rpc
for AccessPolicy
resource.
matcho-rpc
allows access to all endpoints that satisfy specified Matcho rules.
Example
Last updated