Lenient scope search in Cerbos policies
Tags: howto, tutorial, opensource, security
Published: 2023-08-03 12:41:23

Cerbos introduced the concept of Scoped Policies back in v0.13 to address the common use case of modeling hierarchical relationships. Scoped policies enable you to define a dot-separated string describing a position of resource or a principal in the hierarchy. It is an optional feature, only evaluated if passed in a request. The scope field can be used to indicate that a resource or a principal are part of a set of policies that must be evaluated together.

The default behavior of the Cerbos engine when using scoped policies is to expect that a policy file exists for the requested scope. Meaning that if the API request defines `a.b.c` as the scope, there must be a policy file in the policy repository with the `a.b.c` scope defined. Release of Cerbos v0.29 brings something new - a lenient scope search.

Lenient Scope Search means that if a policy with passed scope does not exist in the store, Cerbos will attempt to find a partial match by searching the policy within scopes that are part of the same hierarchy as the passed scope.

This feature is available since Cerbos [v0.29](https://cerbos.dev/blog/shared-variables-globals-scope-updates-and-more-cerbos-v029) so that is the lowest you should aim for in order to be able to use it. See [installation instructions](https://docs.cerbos.dev/cerbos/latest/installation/binary.html) for more information.

## How to use lenient scope search in Cerbos Policies?

Look at the following organizational hierarchy shown below. We can think of it as a tree-like structure. With each of the nodes representing a scope. The top-level node is labeled `Inc`, which represents the entire organization. Underneath `Inc`, there is a child node labeled `Sales`, representing the corporation's sales department. Within the `Sales` department, there is a further child node labeled `EMEA`, which specifically represents the sales operations in the EMEA region. Looking at our tree schema, EMEA (along with the NAM, LATAM and APAC nodes), the Core and Enterprise nodes, as well as the Support and Marketing are all bottom or leaf-level nodes.

![Organizational structure example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8rynn3axzyoovgnb0qgp.png)

In this tree structure, each node corresponds to a scope that can be used in Cerbos policies. For example, the scope `Inc.Sales.EMEA` in the Cerbos request corresponds to the path from the root to the `EMEA` leaf node in the organizational tree (equivalent to `a.b.c` for simplicity in this explanation). Check to learn more about scoped policies.

When evaluating policies, Cerbos will first look for a policy that exactly matches the requested scope `a.b.c` (or `Inc.Sales.EMEA`). If it doesn't find a policy with that specific scope in the policy store, it will apply a lenient scope search behavior. In this search, Cerbos will attempt to find policies with broader scopes, such as `a.b` (or `Inc.Sales`) and even more general scope `a` (or `Inc`). The search will continue until it finds a matching policy, or it reaches the root of the organizational tree (empty scope).

In order to use lenient scope search, you need to set `lenientScopeSearch` field to true in your Cerbos engine configuration:

```yml
engine:
  lenientScopeSearch: true
```

The key requirement for policies in the policy store is that they must have unbroken scope chains, which means policies must be defined for all parent scopes leading up to a specific leaf scope. With `lenientScopeSearch` enabled, Cerbos allows missing policies only at the leaf level (e.g., `EMEA` in the `Sales` department). All parent scopes (e.g., `Sales` and `Inc`) must have defined policies in the store for the lenient scope search to be effective.


## Conclusion
With the introduction of lenient scope search in [Cerbos v0.29](https://github.com/cerbos/cerbos/releases/tag/v0.29.0), managing Cerbos policies gains more flexibility. By setting the configuration field `lenientScopeSearch` to true, Cerbos no longer expects to have every single leaf-level policy file in order to evaluate requests concerning those.