# The Cerbos API

|     |     |
| --- | --- |
|  | This documentation is for<br>a previous<br>version of Cerbos. Choose 0.53.0 from the version picker at the top right or navigate to [https://docs.cerbos.dev](https://docs.cerbos.dev/) for the latest version. |

The main API endpoint for making policy decisions is the `/api/check/resources` REST endpoint (`cerbos.svc.v1.CerbosService/CheckResources` RPC in the gRPC API). You can view the latest API documentation from a running Cerbos instance by accessing the root directory of the HTTP endpoint using a browser.

```sh
docker run --rm --name cerbos -p 3592:3592 -p 3593:3593 ghcr.io/cerbos/cerbos:0.35.1
```

Navigate to [http://localhost:3592/](http://localhost:3592/) using your browser to explore the Cerbos API documentation.

Alternatively, you can explore the API using the following methods as well:

- Using an OpenAPI-compatible software like [Postman](https://www.postman.com/) or [Insomnia](https://insomnia.rest/) to explore the Cerbos OpenAPI spec available at [http://localhost:3592/schema/swagger.json](http://localhost:3592/schema/swagger.json).

- Using [grpcurl](https://github.com/fullstorydev/grpcurl) or any other tool that supports [gRPC server reflection](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md) API to explore the gRPC API exposed on port 3593.

## Client SDKs

- [Go](https://pkg.go.dev/github.com/cerbos/cerbos-sdk-go/cerbos)

- [Java](https://github.com/cerbos/cerbos-sdk-java)

- [JavaScript](https://github.com/cerbos/cerbos-sdk-javascript)

- [.NET](https://github.com/cerbos/cerbos-sdk-net)

- [Laravel](https://github.com/cerbos/cerbos-sdk-laravel)

- [PHP](https://github.com/cerbos/cerbos-sdk-php)

- [Python](https://github.com/cerbos/cerbos-sdk-python)

- [Ruby](https://github.com/cerbos/cerbos-sdk-ruby)

- [Rust](https://github.com/cerbos/cerbos-sdk-rust)

Other languages coming soon

## Demos

|     |     |
| --- | --- |
|  | Demos are constantly being added or updated by the Cerbos team. Visit [https://github.com/orgs/cerbos/repositories?language=&q=demo&sort=&type=all](https://github.com/orgs/cerbos/repositories?language=&q=demo&sort=&type=all) for the latest list. |

- [Application (Python)](https://github.com/cerbos/demo-python)

- [GraphQL Service (NodeJS)](https://github.com/cerbos/demo-graphql)

- [REST Service (Go)](https://github.com/cerbos/demo-rest)

Get help

- [Join the Cerbos community on Slack](http://go.cerbos.io/slack)

- [Email us at](mailto:help@cerbos.dev) [help@cerbos.dev](mailto:help@cerbos.dev)

## Request and response formats

### `CheckResources` (`/api/check/resources`)

This is the main API entrypoint for checking permissions for a set of resources.

#### Request

```json
{
  "requestId": "test", (1)
  "principal": {
    "id": "alice", (2)
    "policyVersion": "20210210", (3)
    "scope": "acme.corp", (4)
    "roles": [ (5)\n      "employee"\n    ],
    "attr": { (6)
      "department": "accounting",
      "geography": "GB",
      "team": "design"
    }
  },
  "resources": [ (7)\n    {\n      "resource": {\n        "id": "XX125", (8)\n        "kind": "leave_request", (9)\n        "policyVersion": "20210210", (10)\n        "scope": "acme.corp", (11)\n        "attr": { (12)\n          "department": "accounting",\n          "geography": "GB",\n          "id": "XX125",\n          "owner": "john",\n          "team": "design"\n        }\n      },\n      "actions": [ (13)\n        "view:public",\n        "approve",\n        "create"\n      ]\n    }\n  ],
  "auxData": { (14)
    "jwt": {
        "token": "xxx.yyy.zzz", (15)
        "keySetId": "ks1" (16)
    }
  },
  "includeMeta": true (17)
}
```

#### Response

```json
{
  "requestId": "test", (1)
  "results": [ (2)\n    {\n      "resource": { (3)\n        "id": "XX125",\n        "kind": "leave_request",\n        "policyVersion": "20210210",\n        "scope": "acme.corp"\n      },\n      "actions": { (4)\n        "view:public": "EFFECT_ALLOW",\n        "approve": "EFFECT_DENY"\n      },\n      "outputs": [ (5)\n        {\n          "src": "resource.leave_request.v20210210/acme#rule-001", (6)\n          "val": "create_allowed:john" (7)\n        },\n        {\n          "src": "resource.leave_request.v20210210#public-view",\n          "val": {\n            "id": "john",\n            "keys": ["foo", "bar", "baz"]\n          }\n        }\n      ],\n      "validationErrors": [ (8)\n        {\n          "path": "/department",\n          "message": "value must be one of \"marketing\", \"engineering\"",\n          "source": "SOURCE_PRINCIPAL"\n        },\n        {\n          "path": "/department",\n          "message": "value must be one of \"marketing\", \"engineering\"",\n          "source": "SOURCE_RESOURCE"\n        }\n      ],\n      "meta": { (9)\n        "actions": {\n          "view:public": {\n            "matchedPolicy": "resource.leave_request.v20210210/acme.corp", (10)\n            "matchedScope": "acme" (11)\n          },\n          "approve": {\n            "matchedPolicy": "resource.leave_request.v20210210/acme.corp"\n          }\n        },\n        "effectiveDerivedRoles": [ (12)\n          "employee_that_owns_the_record",\n          "any_employee"\n        ]\n      }\n    }\n  ],
  "cerbosCallId": "01HHENANTHFD5DV3HZGDKB87PJ" (13)
}
```

### `PlanResources` (`/api/plan/resources`)

Produces a query plan that can be used to obtain a list of resources that a principal is allowed to perform a particular action on.

#### Request

```json
{
  "requestId":  "test01", (1)
  "action":  "approve", (2)
  "resource":  {
    "policyVersion": "dev", (3)
    "kind":  "leave_request", (4)
    "scope": "acme.corp", (5)
    "attr":  { (6)
      "owner":  "alicia"
    }
  },
  "principal":  {
    "id":  "alicia", (7)
    "policyVersion": "dev", (8)
    "scope": "acme.corp", (9)
    "roles":  ["user"], (10)
    "attr": { (11)
      "geography": "GB"
    }
  },
  "includeMeta": true, (12)
  "auxData": { (13)
    "jwt": {
      "token": "xxx.yyy.zzz", (14)
      "keySetId": "ks-1" (15)
    }
  }
}
```

#### Response

```json
{
  "requestId": "test01",
  "action": "approve",
  "resourceKind": "leave_request",
  "policyVersion": "dev",
  "filter": {
    "kind": "KIND_CONDITIONAL", (1)
    "condition": { (2)
        "expression":  {
          "operator":  "eq",
          "operands":  [\
            { "variable":  "request.resource.attr.status" },\
            { "value":  "PENDING_APPROVAL" }\
          ]
        }
    }
  },
  "meta": {
    "filterDebug": "(request.resource.attr.status == \"PENDING_APPROVAL\")" (3)
  },
  "cerbosCallId": "01HHENANTHFD5DV3HZGDKB87PJ" (4)
}
```

#### Structure of the `filter` block

The `kind` field defines the filter kind.

`KIND_ALWAYS_ALLOWED`

The principal is unconditionally allowed to perform the action

`KIND_ALWAYS_DENIED`

The principal is unconditionally not permitted to perfrom the action

`KIND_CONDITIONAL`

The principal is allowed to perform the action if the condition is satisfied

The `condition` field holds the AST of the condition that must be satisfied. It is rooted in an expression that has an `operator` (e.g. equals, greater than) and `operands` (e.g. a constant value, a variable or another expression).

| Operator | Description |
| --- | --- |
| `add` | Addition (+) |
| `and` | Logical AND (&&) |
| `div` | Division (/) |
| `eq` | Equality (==) |
| `ge` | Greater than or equal (>=) |
| `gt` | Greater than (>) |
| `in` | List membership (in) |
| `index` | Array or map index |
| `lambda` | Anonymous function |
| `le` | Less than or equal (⇐) |
| `lt` | Less than (<) |
| `mod` | Modulo (%) |
| `mult` | Multiplication (*) |
| `ne` | Not equal (!=) |
| `not` | Logical NOT |
| `or` | Logical OR |
| `sub` | Subtract (-) |

### Common Operators

Example: `request.resource.attr.status == "PENDING_APPROVAL"`

```json
{
  "expression": {
    "operator": "eq",
    "operands": [\
      {\
        "variable": "request.resource.attr.status"\
      },\
      {\
        "value": "PENDING_APPROVAL"\
      }\
    ]
  }
}
```

Example: `(request.resource.attr.department == "marketing") && (request.resource.attr.team != "design")`

```json
{
  "expression": {
    "operator": "and",
    "operands": [\
      {\
        "expression": {\
          "operator": "eq",\
          "operands": [\
            {\
              "variable": "request.resource.attr.department"\
            },\
            {\
              "value": "marketing"\
            }\
          ]\
        }\
      },\
      {\
        "expression": {\
          "operator": "ne",\
          "operands": [\
            {\
              "variable": "request.resource.attr.team"\
            },\
            {\
              "value": "design"\
            }\
          ]\
        }\
      }\
    ]
  }
}
```

Example: `request.resource.attr.values.filter(t, t > 0)`

```json
{
  "expression": {
    "operator": "filter",
    "operands": [\
      {\
        "variable": "request.resource.attr.values"\
      },\
      {\
        "expression": {\
          "operator": "lambda",\
          "operands": [\
            {\
              "variable": "t"\
            },\
            {\
              "expression": {\
                "operator": "gt",\
                "operands": [\
                  {\
                    "variable": "t"\
                  },\
                  {\
                    "value": 0\
                  }\
                ]\
              }\
            }\
          ]\
        }\
      }\
    ]
  }
}
```

### `ServerInfo` (`/api/server_info`)

Returns Cerbos server version.

#### Response

```json
{
  "version": "0.25.0",
  "commit": "6b5a051a160398a3c04370f742e6090fab2ed0b8",
  "buildDate": "2023-02-13T09:31:48Z"
}
```

## Accessing the API

### Using curl to access the REST API

```sh
cat <<EOF | curl --silent "localhost:3592/api/check/resources?pretty" -d @-
{
  "requestId": "test",
  "principal": {
    "id": "alice",
    "roles": ["employee"],
    "attr": {
      "department": "accounting",
      "geography": "GB",
      "team": "design"
    }
  },
  "resources": [\
    {\
      "resource": {\
        "id": "XX125",\
        "kind": "leave_request",\
        "attr": {\
          "department": "accounting",\
          "geography": "GB",\
          "id": "XX125",\
          "owner": "john",\
          "team": "design"\
        }\
      },\
      "actions": [\
        "view:public",\
        "approve",\
        "create"\
      ]\
    }\
  ]
}
EOF
```

### Using grpcurl to access the gRPC API

```sh
cat <<EOF | grpcurl -plaintext -d @ localhost:3593 cerbos.svc.v1.CerbosService/CheckResources
{
  "requestId": "test",
  "principal": {
    "id": "alice",
    "roles": ["employee"],
    "attr": {
      "department": "accounting",
      "geography": "GB",
      "team": "design"
    }
  },
  "resources": [\
    {\
      "resource": {\
        "id": "XX125",\
        "kind": "leave_request",\
        "attr": {\
          "department": "accounting",\
          "geography": "GB",\
          "id": "XX125",\
          "owner": "john",\
          "team": "design"\
        }\
      },\
      "actions": [\
        "view:public",\
        "approve",\
        "create"\
      ]\
    }\
  ]
}
EOF
```

## Generating API clients

The Cerbos OpenAPI specification can be obtained from a running Cerbos instance by accessing [http://localhost:3592/schema/swagger.json](http://localhost:3592/schema/swagger.json). Cerbos gRPC API definitions are published to the [Buf schema registry (BSR)](https://buf.build/cerbos/cerbos-api) and can be easily added to your project if you use the [Buf build system for protobufs](https://docs.buf.build/).

### REST

There are many tools available to generate clients from an OpenAPI specification. [https://openapi.tools/#sdk](https://openapi.tools/#sdk) is a good resource for finding a tool suitable for your preferred language.

#### Example: Generating a Java client using OpenAPI Generator

|     |     |
| --- | --- |
|  | [OpenAPI Generator](https://openapi-generator.tech/) has [support for many popular programming languages and frameworks](https://openapi-generator.tech/docs/generators#client-generators). Please consult the documentation to find the client generation instructions for your favourite language. |

This is an example of using the popular [OpenAPI Generator](https://openapi-generator.tech/) service to generate a Java client API.

- Download the Cerbos OpenAPI specification

```sh
curl -Lo swagger.json http://localhost:3592/schema/swagger.json
```

- Run the OpenAPI Generator

```sh
docker run --rm -v $(pwd):/oas openapitools/openapi-generator-cli generate -i /oas/swagger.json -g java -o /oas/java
```

### gRPC

**Any language**

You can access the Cerbos protobuf definitions from the [Cerbos source tree](https://github.com/cerbos/cerbos/tree/main/api/cerbos). However, the easiest way to generate client code for your preferred language is to use the [Buf build tool](https://docs.buf.build/) to obtain the published API definitions from the [Buf schema registry (BSR)](https://buf.build/cerbos/cerbos-api).

- Run `buf export buf.build/cerbos/cerbos-api -o proto` to download the API definitions with dependencies to the `proto` directory.

- You can now use [`buf generate`](https://docs.buf.build/generate-usage) or `protoc` to generate code using the protobufs available in the `proto` directory.

- If you don’t want to download protobufs and then to generate code using `buf` or `protoc`, you can use the [Cerbos grpc-tools container](https://github.com/cerbos/grpc-tools) to generate code for languages like Java, NodeJS, Python, C# etc.

**Go**

The [Cerbos Go SDK](https://pkg.go.dev/github.com/cerbos/cerbos/client) uses the gRPC API to communicate with Cerbos. The generated gRPC and protobuf code is available under the `github.com/cerbos/cerbos/api/genpb` package.

```sh
go get github.com/cerbos/cerbos/api
```

You can also make use of the [remote generation feature of Buf schema registry](https://docs.buf.build/tour/use-remote-generation) to pull down the Cerbos gRPC API as a Go module:

```sh
go get go.buf.build/cerbos/gen-go/cerbos/cerbos-api
```
