Getting Started With Rego

Written by mustafab | Published 2022/06/27
Tech Story Tags: debugging | getsentry | monitoring | rego | open-policy-agent | beginners-guide | coding | software-development

TLDRRego is a declarative language for defining rules that are evaluated by the OPA engine. For engineers that are used to imperative languages like Javascript or Python, Rego can look a bit foreign. In this post, we give a few tips for how to get started with reading and writing Rego policies. Each policy is a set of named decisions and their values, and each decision is a header in a block. Rego isn’t a [Turing-complete] language for writing arbitrary programs.via the TL;DR App

We’ve got a pretty great resource for people getting started with rego, originally posted here. Sharing here as well in-case it helps anyone.

Aserto uses theĀ Open Policy AgentĀ (OPA) as the decision engine for evaluating authorization decisions.Ā RegoĀ is the policy language for defining rules that are evaluated by the OPA engine.

For engineers that are used to imperative languages like Javascript or Python, Rego can look a bit foreign. In this post, we give a few tips for how to get started with reading and writing Rego policies.

More like SQL than like a programming language

Rego isn’t aĀ Turing-completeĀ language for writing arbitrary programs. Rather, it’s a declarative language for defining rules - and can be thought of in the same way you think of a query language (like SQL). For all you language geeks, Rego is based onĀ DatalogĀ (a subset of Prolog), and contains some simplifying assumptions that make it easier to learn, easier to implement an evaluator for, and faster to execute.

Packages are namespaces

package aserto.InviteUser

Every Rego file is in aĀ package. This defines the scope for the policy. Policy files that use the same package name are in the same namespace.

Decisions

The result of a policy evaluation is a set of named decisions and their values.Ā  Each decision is a header in a block. For example,

allowed {
  true
}

returnsĀ trueĀ for theĀ allowedĀ decision.

Input documents

The inputs to a policy are all keyed in anĀ inputĀ variable. Aserto automatically mapsĀ input.userĀ to the properties of the user in the context of which the policy is evaluated, andĀ input.resourceĀ to the resource that is passed in as an optional resource context.

Using values from the input document in the policy

In the policy below,Ā allowedĀ returnsĀ trueĀ only if theĀ fooĀ attribute on the input map is equal to the stringĀ "bar".

allowed {
  input.foo == "bar"
}

Multiple decision outputs

You can have more than one named decision in a policy. For example, in the policy below, there are two decisions (allowedĀ andĀ enabled), and enabled takes the value ofĀ allowed.

allowed {
  input.foo == "bar"
}

enabled {
  allowed
}

Expressions inside a decision block are ā€œAND-edā€ together

In the policy below, both conditions must beĀ trueĀ for the allowed decision to evaluate toĀ true.

allowed {
  input.foo == "bar"
  input.bar == "baz"
}

Note that the conditions can be listed in any order - Rego doesn’t care about order when it comes to evaluation.

Blocks with the same name are ā€œOR-edā€ together

In the policy below,Ā allowedĀ isĀ trueĀ ifĀ fooĀ isĀ "bar", OR ifĀ barĀ isĀ "baz".

allowed {
  input.foo == "bar"
}

allowed {
  input.bar == "baz"
}

Data documents

You can embed a data document namedĀ data.jsonĀ in a Rego policy. This document is namespaced based on the directory it is in. For example,Ā roles/data.jsonĀ will show up as an object calledĀ data.rolesĀ in the policy evaluation context.

With the document below,

mydata/data.json:

{
  "hello": "world"
}

You could write a policy that accesses it in the following way:

allowed {
  input.hello == data.mydata.hello
}

TheĀ allowedĀ decision would evaluate toĀ trueĀ ifĀ input.helloĀ was equal toĀ "world".

Expressions over arrays

Rego has set operators that make it easy to construct expressions over each value in an array. For example, ifĀ input.user.rolesĀ is an array that can contain one or more roles, the following policy will returnĀ trueĀ for theĀ allowedĀ decision if any of the roles in the array is equal toĀ "viewer":

allowed {
  some i
  input.user.roles[i] == "viewer"
}

Note that writing an expression over an array means iterating over every value of that array - a bit like a database table scan. That’s why at Aserto we prefer Rego objects over arrays, since indexing into an object using a key is a constant-time operation.

Summary

Rego is an expressive policy language that can be used to construct a wide variety of RBAC and ABAC-style policies. We’ve gone through the most common patterns to get you started on writing authorization policies in Rego. Happy hacking!


Also Published Here


Written by mustafab | Yes, I work for an authorization startup. No, I'm not in the sales department.
Published by HackerNoon on 2022/06/27