# Rego

## **What is Rego?**

Rego is a high-level, declarative policy language designed to be expressive, flexible, and human-readable. It is used by OPA to define policies that determine whether certain actions should be allowed or denied based on input data. Rego policies are evaluated by OPA to produce decisions, such as "allow" or "deny," that can be enforced across different systems and applications.

Rego is particularly powerful in cloud-native environments because it allows you to express complex policy decisions in a concise and manageable way. It is designed to work with JSON data, making it a natural fit for modern applications and services.

### **Basic Structure of a Rego Policy**

A Rego policy is composed of a set of rules, where each rule defines a condition that must be met for the policy to return a specific result. The basic components of a Rego policy include:

* **Package Declaration**: Defines the namespace for the policy.
* **Rules**: Logical conditions that return a boolean value (`true` or `false`) or other data types.
* **Input**: The data against which the policy is evaluated.
* **Expressions**: Logical and arithmetic operations used within rules.

**Example of a Simple Rego Policy:**

```rego
package example

default allow = false

allow {
    input.user == "alice"
    input.action == "read"
}
```

* **Package**: The `package example` statement defines the namespace under which the rules are defined.
* **Default Rule**: The `default allow = false` statement sets the default value of the `allow` rule to `false`, meaning actions are denied unless explicitly allowed.
* **Rule**: The `allow` rule checks whether the `input.user` is `"alice"` and the `input.action` is `"read"`. If both conditions are true, the rule returns `true`, allowing the action.

### **Understanding Rego Syntax and Basic Concepts**

Rego is a declarative language, meaning it describes *what* should be done rather than *how* to do it. Here are some key concepts to understand when writing Rego policies:

* **Rules**: Rules are the core of Rego policies. They define conditions that must be satisfied for the rule to return `true` or a specific value.
* **Variables**: Rego uses variables to store values and results of expressions. Variables are created by assignment (`=`) and can be used in subsequent expressions.
* **Expressions**: Expressions are logical or arithmetic statements that return a value. They can involve comparisons (`==`, `!=`, `<`, `>`, etc.), arithmetic operations (`+`, `-`, `*`, `/`), and functions.
* **Input**: The `input` keyword represents the data that is passed to the policy for evaluation. It is typically a JSON object.

**Example:**

```rego
package example

allow {
    input.user == "alice"
    input.role == "admin"
}
```

In this example, the `allow` rule will return `true` if the `input.user` is `"alice"` and the `input.role` is `"admin"`.

**Working with Collections: Arrays, Objects, and Sets**

Rego supports working with various data structures, including arrays, objects, and sets, which are essential for writing more complex policies.

* **Arrays**: Ordered collections of values. Access elements using indexing (`array[index]`).
* **Objects**: Unordered collections of key-value pairs. Access values using keys (`object.key`).
* **Sets**: Unordered collections of unique values. Rego provides special syntax for working with sets.

**Example:**

```rego
package example

allow {
    input.user == "alice"
    input.roles[_] == "admin"  # Checks if "admin" is in the list of roles
}
```

In this example, `input.roles` is an array, and the rule checks if `"admin"` is one of the roles assigned to the user.

### **Writing Complex Policies with Logical Operators**

Rego allows the use of logical operators (`and`, `or`, `not`) to combine multiple conditions within a rule.

**Example:**

```rego
package example

allow {
    input.user == "alice"
    input.action == "read"
    not input.resource == "restricted"  # Allow only if resource is not "restricted"
}
```

In this policy, the `allow` rule returns `true` if the user is `"alice"`, the action is `"read"`, and the resource is not `"restricted"`.

**Functions in Rego**

Rego provides built-in functions for common tasks such as string manipulation, data aggregation, and type conversion. You can also define custom functions using Rego rules.

**Example: Using Built-in Functions**

```rego
package example

allow {
    input.user == "alice"
    count(input.roles) > 2  # Allow only if user has more than 2 roles
}
```

In this example, the `count` function is used to determine the number of roles assigned to the user.

**Example: Custom Function**

```rego
package example

is_admin(user) {
    user.role == "admin"
}

allow {
    is_admin(input.user)
}
```

Here, a custom function `is_admin` is defined to check if a user has the `admin` role, and it is used in the `allow` rule.

**Debugging Rego Policies**

When writing Rego policies, it’s important to test and debug them to ensure they work as expected. OPA provides several tools to assist with debugging:

* **Tracing**: Use the `trace` function to output information during policy evaluation.
* **Explanation**: The `--explain` flag in the OPA CLI provides detailed information on how a policy was evaluated.
* **Testing**: Rego allows you to write test cases to validate your policies (covered in a later lesson).

**Example: Using Trace for Debugging**

```rego
package example

allow {
    trace("Evaluating if user is alice")
    input.user == "alice"
}
```

Running this with tracing enabled (`opa eval --explain=full ...`) will show the trace output, helping you understand the evaluation process.

### **Summary**

In this lesson, you’ve been introduced to Rego, the policy language of OPA. You learned about its basic structure, how to write simple policies, and how to use Rego’s syntax and operators. You also explored working with collections, writing complex policies, and using functions in Rego.
