Home > Software design >  How to I combine the results of multiple rules
How to I combine the results of multiple rules

Time:04-04

I have 3 roles and I am trying to return what actions a user can do based on the assigned roles.

Playground: https://play.openpolicyagent.org/p/5gN7ObojXh

The first part should check if the object being processed is in a list, and then if the role(s) return any actions.

I'm very new to OPA and Rego and I am finding it to be very confusing when anything more than simple comparisons are required.

CodePudding user response:

Rules in OPA are either complete or partial. Complete rules are those that evaluate to a single value, and as such will fail if evalutated to different, conflicting values — e.g. a boolean "allow" rule can't be both true and false.

Partial rules either return sets or objects, and are built incrementally by evaluating each rule with the same name and adding the result to the set/object produced by the rule.

Example policy using a partial rule to build a set might look something like this:

package policy

import future.keywords.in

deny["Username found in deny list"] {
    input.user.name in data.users.denylist
}

deny[msg] {
    not "read" in input.user.roles
    msg := sprintf("User %v missing role 'read'", [input.user.name])
}

deny["/admin endpoint requires 'admin' role"] {
    input.request.path[0] == "admin"
    not "admin" in input.user.roles
}

When evaluated with an input like the below:

{
  "input": {
    "user": {
      "name": "bob",
      "roles": ["developer"]
    },
    "request": {
      "path": ["admin", "users"]
    }
  }
}

The deny rule might evaluate to:

[
  "User bob missing role 'read'",
  "/admin endpoint requires 'admin' role"
]

The example policy you provided could be rewritten to use incremental rules, like this: https://play.openpolicyagent.org/p/MYFFAVqMCu

If you'd like to learn more, the Styra Academy is a great complementary resource to the OPA docs.

  • Related