Flexible policy composition - Injecting environment specific information into Cerbos policies
Tags: howto, tutorial, security, opensource
Published: 2023-07-31 09:56:17

Since early days, Cerbos introduced `version` field to support use cases such as gradual rollout of a new version of an application or having different policies for different environments (production, staging etc.). When a request did not explicitly specify the policy version, the Cerbos engine would attempt to find a matching policy that has its version set to `default`. But for each environment you had to have a different version of Cerbos policies defined.

With the release of [v0.29](https://cerbos.dev/blog/shared-variables-globals-scope-updates-and-more-cerbos-v029) Cerbos introduces global variables. Global variables provide a convenient way to inject information from the environment where the Policy Decision Point (PDP) is running directly into your policies. This feature is particularly useful to implement environment-specific authorization rules, like “developers have access to everything in staging”, without having to maintain separate policy versions per environment. 

While creating environment-specific policy versions is still recommended for promoting changes between environments, global variables offer an alternative approach that can simplify policy management. This piece will show you how to use the new `globals` field to define a single set of access control policies for multiple environments.

## How to use globals with Cerbos Policies?

The first thing you need to do is update your version of Cerbos accordingly. Global variables are available since v0.29 so that is the lowest you should aim for in order to be able to use `globals`. See [installation instructions](https://docs.cerbos.dev/cerbos/latest/installation/binary.html) for more information.

In earlier versions of Cerbos, in case you needed environment-specific information, you were expected to create separate policy versions for each environment. That can be tedious and error-prone, and you’d end up with a multiple configurations, for example:
- policy_dev.cerbos (for development environment)
- policy_staging.cerbos (for staging environment)
- policy_prod.cerbos (for production environment)

Each of them would have a different version names (dev, staging and prod respectively) and separate rules definitions, most of which may be identical regardless of the environment. That in theory means you’d have to edit your policy in three places to cover all 3 of the above mentioned environments.

With the introduction of `globals` in Cerbos v0.29 you can now inject environment-specific information without creating separate policy versions.

In order to specify the environment Cerbos engine is running in, you need to define a global variable. In this example, we named it `env` and added it under the `engine.globals` section of the given config file.

```yml
engine:
  globals:
    env: "staging"
```

This variable can now be referenced in policy conditions as `globals.env`. 

Let’s say we have an HR system, and are writing policies for leave request handling. We can choose to enforce/ignore certain rules for certain environments by simply stating that as a part of a rule condition. 

```yml
---
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  variables:
    local:
      principal_location: (P.attr.ip_address.inIPAddrRange("10.20.0.0/16") ? "GB" : "")
  version: "default"
  scope: "our.app.uk"
  resource: leave_request
  rules:
    - actions: ["delete"]
      condition:
        match:
          any:
            of:
              - expr: globals.env == "staging"
              - expr: request.resource.attr.geography == variables.principal_location
      effect: EFFECT_ALLOW
```

Additionally, you can use environment variables to set global values. For example:

```yml
engine:
  globals:
    env: ${CERBOS_ENVIRONMENT:staging}
```

## Conclusion
With the introduction of `globals` in [Cerbos v0.29](https://github.com/cerbos/cerbos/releases/tag/v0.29.0), it’s easier to create environment-specific authorization rules without having to maintain separate policy versions for each environment. 

By using global variables, you can streamline your access control setup and improve the overall maintainability and consistency of your Cerbos policies across various environments.