Embedded Policy Decision Point

Exclusive to Cerbos Hub is the ability to generate self-contained policy bundles that can be embedded into any system that supports WebAssembly modules. This is a powerful solution for cases where authorization decisions have to be made locally on device or at the edge without access to a full-fledged Cerbos policy decision point. A common use case for embedded policies is to enable web applications to make decisions about which UI elements to render without making calls to a backend service.

Picking policies to be included

By default, all the policies found in your policy repository are included in the embedded PDP bundle. You can restrict the set of policies included in the bundle by adding the hub.cerbos.cloud/embedded-pdp annotation as follows.

apiVersion: api.cerbos.dev/v1
metadata:
  annotations:
    hub.cerbos.cloud/embedded-pdp: "true"
resourcePolicy:
  version: default
  resource: purchase_order

The inclusion logic is as follows.

  • If none of the policies in the repo are annotated, they are all included

  • If at least one policy is annotated, only that policy and its dependencies are included. Note that dependencies include ancestors of scoped policies. For example, if you annotate a policy that has the scope a.b, its ancestors (scope a and no-scope) are included automatically regardless of whether they are annotated or not.

You can use the cerbosctl hub epdp list-candidates /path/to/policy/repo command to list all the policies that will be included in the embedded PDP bundle. See cerbosctl documentation for more information.

Using an embedded policy decision point

The Cerbos Embedded Javascript SDK is designed to work with the embedded PDPs generated by Cerbos Hub and exposes the same simple API interface for checking permissions.

To get started, install the package:

npm install @cerbos/embedded
import { AutoUpdatingLoader, Embedded } from "@cerbos/embedded";

const cerbos = new Embedded(
  new AutoUpdatingLoader(
    "https://lite.cerbos.cloud/bundle?workspace=...&label=...",
  ),
);

// The cerbos.checkResource() method can now be used to check permissions locally
await cerbos.isAllowed({
  principal: {
    id: "user@example.com",
    roles: ["USER"],
    attr: { tier: "PREMIUM" },
  },
  resource: {
    kind: "document",
    id: "1",
    attr: { owner: "user@example.com" },
  },
  action: "view",
}); // => true