Skip to main content

Frequently Asked Questions (FAQ)

This page aims to answer the FAQs about Policy Builder.

What is Policy Builder?

Styra’s Policy Builder provides a guided, point-and-click approach to policy authoring for occasional policy developers and users with less technical backgrounds. Policy Builder is an alternative to writing Rego.

What is Policy as Code?

Policy as code allows the rules that govern a software system to be defined using a human-readable, declarative language so that policies can be managed with the same version control systems and tools that a DevOps team uses to manage application code. Styra’s Policy Builder produces Rego source code that integrates seamlessly with hand-written Rego policies, combining the user experience benefits of a graphical user interface with the reliability of policy as code.

What is a package?

A package is a collection of related source files consisting of rules and helper functions under a single namespace. When queried, a package generates a JSON object whose keys are the package’s rule names (assuming each rule generates a value. For more information, see the What is a rule? section.

Why is the package name read-only?

Styra DAS requires every package name to match the directory layout of the files that contribute to the package. In other words, a package name can’t be changed without also changing the corresponding directory layout. Considering this limitation, Policy Builder focuses on authoring policies rather than organizing the packages and directory layouts.

What is an import?

Import statements declare dependencies that a policy has on data and rules defined outside a given package. All such dependencies exist in one of two root namespaces: data (other packages) or input (query arguments). Imported items can be referenced in the policy using simple identifiers instead of absolute references (my_package instead of data.path.to.my_package, for example).

What is a constant?

A constant is a special kind of rule that generates a single, unchanging value. The simplest constants are just scalar values such as true, 1, or "hello".

What is a rule?

A rule is a collection of conditions that can be intuitively understood as condition-1 AND condition-2 AND ... condition-N. When all of a rule’s conditions are satisfied, the rule generates a value.

There are three kinds of rules:

  • Complete: Defines a single value

  • Partial object: Defines one or more key-value pairs in an object

  • Partial set: Defines one or more values in a set

What is a function?

A function is a special kind of rule that accepts arguments. Unlike rules (which contribute their names and values to the package namespace), functions only produce values when called from a policy; they cannot be queried otherwise. Functions are therefore best thought of as utilities for other rules.

What is the difference between OR and ELSE?

If the same rule is defined more than once, each instance will be evaluated to determine the resulting value. Although, the order in which these rules are evaluated isn’t important, the process can be intuitively understood as <rule-1> OR <rule-2> OR ... <rule-N>.

If you need strict control over order of evaluation, use else. Rules grouped together in this way will be evaluated in strict order until a match is found or there are no more else clauses to evaluate.

What happened to the rule I added?

It is important to know that Policy Builder groups all rules of the same name together as OR blocks below the first rule so that each rule’s logic is easier to understand and the policy layout is consistent. With this concept, when you add a new rule to your policy, it will be grouped with any existing rules of the same name. This implies that you may add a rule in the Builder view only to watch the rule seemingly vanish after you save it. But, the rule did not disappear, Policy Builder moved it into the existing group of rules with the same name.

How do I know which values are valid?

Policy Builder input validation is based primarily on a syntax parser. The resulting validation errors are often inscrutable (we are working to improve these). Valid values typically take the form of valid Rego-booleans (true), numbers (1), strings ("hello"), objects ({"a": 1}), sets ({2, 3, 5, 7}), references (input.url), variables (x), operators (==), and so on.

How do I use variables?

  • Scoping: Variables are taken from the global scope unless they (a) do not exist there or (b) they have been explicitly declared local to the body of a rule or function. You can declare a local variable using the := operator: x := input.url. Or you can explicitly designate certain variables to be local using the Policy Builder’s Local variables condition.

  • Binding: Conceptually, the first instance of a variable in a rule or function body is unbound (that is, it does not have a defined value). There are three ways that a variable becomes bound:

    • Using the variable with an assignment operator (x := input.url) binds the right-hand value to the left-hand variable.

    • An unbound variable in a reference context (for example, my_set[x]) iterates over the referenced collection. The rule will be evaluated once for every possible value of x in my_set.

    • Unification (=) combines assignment and equality; it automatically searches for variable substitutions that make a condition’s left- and right-hand sides equal. In other words, it unifies them. For example, the following condition [a, b] = ["hello", "world"] destructures the left-hand array ["hello", "world"], assigning "hello" to variable a and "world" to variable b.

  • Returning: The value that a rule or function generates can either be constant (for example, allow is true when input.url == "/") or taken from a variable defined in the rule or function body (for example, href is x when x := input.url).