Migrating from PlainID to Cerbos

AAlex OlivierOctober 27, 202610 min read
Migrating from PlainID to Cerbos

This guide is for teams that run PlainID today and are moving authorization to Cerbos, or want to know what the move involves before a renewal.

Most of what you built around PlainID carries over. Your enforcement points stay where they are, and the access rules your business agreed stay the same. Your identity provider and governance tools keep doing their jobs.

What changes is where policy lives and how it is reviewed, where attribute data comes from, and which component each enforcement point asks for a decision.

Why migrating from PlainID is mostly an authoring and data question

Translating rules is the smallest part of the work. Most PlainID policies express familiar ideas, roles, attributes, conditions on the resource and on the context, and those map cleanly to Cerbos policies.

The real work is in two places.

The first is moving policy out of a console and into a review process, so every rule has an owner, a reviewer and tests.

The second is making attribute data explicit. In PlainID, policy information points pull attributes from your systems behind the scenes. In Cerbos, the application sends what it already knows, and Cerbos Synapse fetches the rest at decision time. Getting the attribute mapping right is what makes decisions match.

What replaces PlainID after you migrate

PlainID's administration console, decision points, policy information points, Authorizers and audit reports become parts of one Cerbos platform.

  • Policy administration moves to policy files in Git or Cerbos Hub policy stores. Changes go through code review and tests, and Cerbos Hub distributes them to every decision point. Cerbos Hub runs hosted, or on-premise for enterprise customers.
  • Decision points become Cerbos decision points running in your infrastructure, as a service, sidecar, DaemonSet or serverless function. They keep working if Cerbos Hub is unreachable.
  • Policy information points become Cerbos Synapse data sources, which fetch identity, resource and relationship data from identity providers, databases and APIs, with caching you configure.
  • Authorizers become SDK calls in your applications and Cerbos Synapse integrations at the gateway, mesh and data layers (Envoy, Istio, Trino, Kafka).
  • Audit reports become decision logs that Cerbos Hub collects from every decision point, searchable and exportable, each linked to the policy version that made the decision.

migrating-from-plainid-to-cerbos - PlainID to Cerbos platform mapping (1).png

Key Cerbos principles to know before you translate

Policies are organized by resource. Every rule about who can do what to an account lives in the account policy. Reviewers find all the rules for a resource in one file, which is easier to audit than rules spread across a console's views.

Everything is denied unless a policy allows it. If no rule matches, the answer is no. An incomplete policy can never grant access by accident.

Schemas catch bad inputs early. You can define the attributes each principal and resource should carry. A service that sends the wrong shape is caught in testing, not in production.

Policies are readable. A security reviewer or product owner can follow a Cerbos policy without learning a policy language. That is what makes code review of access rules practical at the scale of thousands of policies.

PlainID to Cerbos concept mapping

PlainID concept Cerbos equivalent Migration note
Workspaces, policies and policy metadata Policy repository or Cerbos Hub policy stores, with scoped policies for tenants or business units Decide ownership and review rules before translating anything
Subject (identity) and its attributes Principal, with roles and attributes Keep identifiers the same so both systems see the same person
Asset types and assets Resource kinds and resource attributes One Cerbos resource policy per asset type is a good starting point
Actions Actions Usually a direct copy
Rules and conditions Rules with CEL conditions, and derived roles for reusable context such as "manager of this account" Write the business rule in plain words first, then in policy
Policy information points and caching views Cerbos Synapse data sources with cache settings Record the source and acceptable staleness for every attribute
PDP, cloud or self-managed Cerbos decision points in your infrastructure Place them next to the workloads that call them
Authorizers for gateways and applications SDK calls, and Cerbos Synapse for Envoy, Istio, Kafka and Trino Keep the enforcement point and swap what it calls
SQL Authorizer filtering and masking Query plans through an ORM adapter, or Cerbos policy outputs for Trino Validate returned rows and masked columns per data platform
Authorization and administration audit reports Cerbos Hub audit log collection, plus Git history for policy changes Agree with your audit team what evidence they need first

A worked example of translating a PlainID policy to Cerbos

Take a typical PlainID policy at a bank. Analysts may read accounts in their own region. Relationship managers may read and update the accounts they manage. Payments above an analyst's approval limit are not allowed.

In PlainID this might be built in the console as a policy on the account asset type, with conditions on the analyst's region and on the account's manager. Here is the same intent in Cerbos.

First, a derived role for "manager of this account", so the condition is written once and reused.


# derived_roles/account_roles.yaml
apiVersion: api.cerbos.dev/v1
derivedRoles:
 name: account_roles
 definitions:
   - name: account_manager
     parentRoles: ["relationship_manager"]
     condition:
       match:
         expr: R.attr.managerId == P.id

Then the resource policy for accounts.


# resources/account.yaml
apiVersion: api.cerbos.dev/v1
resourcePolicy:
 resource: account
 version: default
 importDerivedRoles: ["account_roles"]
 rules:
   # Analysts read accounts in their own region
   - actions: ["read"]
     effect: EFFECT_ALLOW
     roles: ["analyst"]
     condition:
       match:
         expr: R.attr.region == P.attr.region


   # Relationship managers read and update the accounts they manage
   - actions: ["read", "update"]
     effect: EFFECT_ALLOW
     derivedRoles: ["account_manager"]


   # Analysts approve payments up to their own limit
   - actions: ["approve_payment"]
     effect: EFFECT_ALLOW
     roles: ["analyst"]
     condition:
       match:
         expr: R.attr.paymentAmount <= P.attr.approvalLimit

A security reviewer can read each rule and match it to the business requirement. Everything not listed is denied.

The approval limit is the kind of value PlainID would fetch through a policy information point. In Cerbos the application can send it, or Cerbos Synapse can fetch it from your system of record at decision time. Set the cache time short for values that change often, so a limit raised an hour ago is evaluated as raised.

Port the tests before you port anything else

Write down the decisions PlainID makes today as Cerbos tests. They become the definition of "the migration is correct".


# tests/account_test.yaml
name: AccountTestSuite
principals:
 amira:
   id: amira
   roles: ["analyst"]
   attr:
     region: emea
     approvalLimit: 10000
 dan:
   id: dan
   roles: ["relationship_manager"]
resources:
 emea_account:
   kind: account
   id: acc-1
   attr:
     region: emea
     managerId: dan
     paymentAmount: 5000
 us_account:
   kind: account
   id: acc-2
   attr:
     region: us
     managerId: someone_else
     paymentAmount: 25000
tests:
 - name: Analysts read in-region accounts and approve within their limit
   input:
     principals: ["amira"]
     resources: ["emea_account", "us_account"]
     actions: ["read", "approve_payment"]
   expected:
     - principal: amira
       resource: emea_account
       actions:
         read: EFFECT_ALLOW
         approve_payment: EFFECT_ALLOW
     - principal: amira
       resource: us_account
       actions:
         read: EFFECT_DENY
         approve_payment: EFFECT_DENY
 - name: Relationship managers update only the accounts they manage
   input:
     principals: ["dan"]
     resources: ["emea_account", "us_account"]
     actions: ["update"]
   expected:
     - principal: dan
       resource: emea_account
       actions:
         update: EFFECT_ALLOW
     - principal: dan
       resource: us_account
       actions:
         update: EFFECT_DENY

Run the tests in CI on every change. In Cerbos Hub, a policy change that fails its tests never reaches a decision point, and the previous version keeps serving.

migrating-from-plainid-to-cerbos - from business rule to policy to test (1).png

Where your PlainID attribute data goes after the migration

List every attribute your PlainID policies use, and for each one, decide who supplies it.

  • The application already has it. Send it in the request. This is the fastest path and keeps decisions predictable.
  • It lives in an identity provider, a database or an API. Use a Cerbos Synapse data source to fetch it at decision time, with a cache that matches how often it changes. Synapse connects to identity providers such as Okta and Microsoft Entra ID, SQL databases and HTTP APIs. Custom extensions cover anything else.
  • It is a relationship, such as "member of this team" or "manager of this account". Supply it as an attribute and use a derived role, as in the example above, or fetch it through Synapse.

Write down the source and the acceptable staleness for each attribute. That list is also what your audit team will want to see.

Replacing PlainID PDP and Authorizer calls with Cerbos

Keep every enforcement point where it is, and change what it asks.

Applications that ask PlainID's PDP for a permit or deny call Cerbos through one of the SDKs, available in eight languages plus Laravel.


import { GRPC } from "@cerbos/grpc";


const cerbos = new GRPC("cerbos:3593", { tls: false });


const decision = await cerbos.checkResource({
 principal: { id: "amira", roles: ["analyst"], attr: { region: "emea" } },
 resource: { kind: "account", id: "acc-1", attr: { region: "emea" } },
 actions: ["read"],
});


if (decision.isAllowed("read")) {
 // show the account
}

Applications that ask for the list of records a user can see use a query plan. Cerbos returns a filter derived from the same policy, and an adapter turns it into a query for your ORM or data layer. See filtering database results with query plans.

Gateway and service mesh Authorizers are replaced by Cerbos Synapse as the external authorization service for Envoy and Istio. The gateway keeps its configuration shape. Only the service it calls changes.

Data platform Authorizers move differently per platform. For Trino, Cerbos policy produces row filters and column masks that Trino enforces. Where you rely on PlainID's masking inside Snowflake or Databricks, keep it in place for now and move it last.

Applications you cannot change stay behind a gateway that calls Cerbos, with no code changes.

Running Cerbos beside PlainID in shadow mode

Before Cerbos enforces anything, run it next to PlainID on real traffic.

  1. Send every request to both. At each enforcement point you are migrating, call Cerbos alongside PlainID, but keep enforcing PlainID's answer.
  2. Log both decisions. Cerbos Hub collects every Cerbos decision with its inputs and the policy that matched, so a mismatch can be traced to a rule or a missing attribute.
  3. Fix any mismatch. Most mismatches are attributes that PlainID fetched and Cerbos did not receive. The rest are rules that were broader or narrower than anyone remembered. Each fix becomes a test.
  4. Agree the exit bar. Set it with your security team before you start. For example, zero unexplained mismatches over two weeks of production traffic for the service.

Moving over to Cerbos and decommissioning PlainID

Move enforcement one service at a time, once that service meets the exit bar. Keep PlainID running for the services not yet moved, then for a short rollback window after the last one. Export PlainID's audit reports for the retention period your regulators require before you switch it off.

At cutover, check three things with your audit team.

  • Cerbos Hub is collecting decision logs from every decision point.
  • Policy changes are going through review.
  • You can answer "show me the policy that was in effect at the time" for any decision since cutover.

Common challenges when migrating from PlainID, and how to solve them

Policies that only exist in the console. Some rules were built visually and never exported. Rebuild them from their business intent, not from screenshots. Write the rule in plain words, agree it with its owner, then write the policy and the test.

Attributes fetched behind the scenes. PlainID's policy information points hid where some attributes came from. Map each one explicitly, as described above. This is the most common source of mismatches in shadow mode.

Business owners who used to edit rules directly. Give them a review role instead. They approve the pull request for their rules, and the Cerbos Hub playground lets them try a change and see the permissions matrix before it is proposed.

Warehouse masking. Move it last, or keep it where it runs. Everything else can move first.

Thousands of policies. Group them by resource type, and move one type per release. The first resource type sets the patterns for request shape, attributes and tests that every later one reuses.

Planning your migration from PlainID

Start with the service that has the fewest attribute sources and enforcement points, not the most important one. Settle the request shape and the attribute mapping there, then reuse them for the harder services. Start early enough that you go into your next PlainID renewal with at least one service running on Cerbos against your own traffic, and a mismatch log that shows how close the rest is.

Book a call and bring one PlainID policy and its attribute sources. We will model it in Cerbos with you, port its tests, and help you build a migration plan, timeline and risk view your security and audit teams can review. To start on your own, try Cerbos for free to build, test and manage your translated policies.

Go deeper:

FAQ

Free policy workshop

Get your first Cerbos policy written by our team.

Book a session to talk through your requirements and walk away with a working policy.

Book a session