Schemas

Cerbos policies rely on context data about the principal and the resource(s) that are submitted through the attr fields of the API request. While the free-form nature of these fields gives you maximum flexibility to author policies that work on data of any shape or form, they can become difficult to reason about and make it harder to enforce system-wide standards and conventions.

Using the JSON Schema support built into Cerbos, you can define schemas for all your principal and resource attributes on a per-resource basis by specifying them in the resource policy. The Cerbos PDP will validate the incoming requests and either log warnings or completely reject them based on the schema enforcement configuration in effect.

Define schemas

Cerbos schemas are standard JSON Schemas (draft 2020-12). If you are using any of disk, git or blob storage drivers the schemas are expected to be in a special directory named _schemas located at the root of the storage directory or bucket. Use the Admin API to add or update schemas if you are using one of the database drivers.

To avoid repetition, you can define common schema fragments inline using $defs or refer to other schemas using $ref (see https://json-schema.org/understanding-json-schema/structuring.html). When using $ref to refer to another schema stored in Cerbos storage, make sure to use an absolute URL with cerbos as the scheme. For example, use cerbos:///common/address.json to refer to a schema file stored in _schemas/common/address.json (if using one of the disk-based stores). This ensures that policies remain portable between different environments.

customer.json: a schema that references another schema to avoid repetition
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "first_name": { "type": "string" },
    "last_name": { "type": "string" },
    "shipping_address": { "$ref": "cerbos:///address.json" },
    "billing_address": { "$ref": "cerbos:///address.json" }
  },
  "required": ["first_name", "last_name", "shipping_address", "billing_address"]
}
address.json: the schema referenced by customer.json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "street_address": { "type": "string" },
    "city": { "type": "string" },
    "state": { "type": "string" }
  },
  "required": ["street_address", "city", "state"]
}

Validate requests using schemas

First, update your resource policy to point to the schemas that should be used to validate requests for that resource kind. For example, the following resource policy requires all requests for album:object resource kind to be validated using principal.json for the principal attributes and album/object.json for the resource attributes respectively.

Example
---
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  importDerivedRoles:
    - apatr_common_roles
  resource: "album:object"
  rules:
    - actions: ['create']
      effect: EFFECT_ALLOW
      derivedRoles:
        - owner

    - actions: ['view']
      effect: EFFECT_ALLOW
      roles:
        - user
      condition:
        match:
          expr: request.resource.attr.public == true

  schemas: (1)
    principalSchema: (2)
      ref: cerbos:///principal.json
    resourceSchema: (3)
      ref: cerbos:///album/object.json
      ignoreWhen: (4)
        actions: ['create', 'delete:*']
1 Schema definition block. Optional. Leave this out if you do not want to use schema validation for this resource type.
2 Schema for validating the principal attributes. Optional. Leave this out if you do not want to validate the principal.
3 Schema for validating the resource attributes. Optional. Leave this out if you do not want to validate the resource.
4 Ignore block. Optional. Define the actions for which schema validation should be ignored. This is useful for special cases like CREATE where your resource might not have all the required attributes to pass schema validation.

Finally, configure the schema enforcement level of the Cerbos PDP to either warn or reject and restart it. Now the PDP will validate any requests where the matching resource policy has schemas specified.

If enforcement level is reject and the request is invalid according to the schema, the effect for all actions will be set to EFFECT_DENY. If enforcement level is warn, then Cerbos will still evaluate the policies and return the effects determined by the policy.

Example: CheckResourceSet API response containing validation errors
{
  "requestId": "test",
  "resourceInstances": {
    "XX125": {
      "actions": {
        "approve": "EFFECT_DENY",
        "create": "EFFECT_DENY",
        "defer": "EFFECT_ALLOW",
        "view:public": "EFFECT_ALLOW"
      },
      "validationErrors": [
        {
          "path": "/department",
          "message": "value must be one of \"marketing\", \"engineering\"",
          "source": "SOURCE_PRINCIPAL"
        },
        {
          "path": "/department",
          "message": "value must be one of \"marketing\", \"engineering\"",
          "source": "SOURCE_RESOURCE"
        }
      ]
    }
  }
}