惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

云风的 BLOG
云风的 BLOG
V
Visual Studio Blog
人人都是产品经理
人人都是产品经理
The GitHub Blog
The GitHub Blog
月光博客
月光博客
T
Tailwind CSS Blog
小众软件
小众软件
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Proofpoint News Feed
B
Blog RSS Feed
博客园 - 司徒正美
A
About on SuperTechFans
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 聂微东
Microsoft Security Blog
Microsoft Security Blog
Recent Announcements
Recent Announcements
博客园 - Franky
U
Unit 42
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Microsoft Azure Blog
Microsoft Azure Blog
T
The Blog of Author Tim Ferriss
GbyAI
GbyAI
Apple Machine Learning Research
Apple Machine Learning Research

Cerbos - All Posts

Authentik vs Keycloak: Self-hosted IdP comparison Mapping business requirements to authorization policy for automotive Fine-grained authorization for AI gateways EIC 2026: Stop counting agents, protect what they can touch Agent skill for writing authorization policies in Claude Desktop Identity security in 2026 EIC 2026 takeaways: the identity stack built for humans will not hold up for AI agents Already have authentication? Here's the authorization layer you still need. Tokens are authorization decisions: a guide to policy-driven token issuance What is a Runtime Authorization Platform It's a dimmer switch, not a kill switch. How CISOs are rethinking AI agent governance From maps to bitmaps (and from bitmaps to bitmaps) AuthZEN, Shared Signals, SCIM Events, IPSIE: Notes from the OpenID Enterprise Panel How do you update authorization policies without redeploying your application? IIW42 recap: Where agent authorization got real Cerbos PDP v0.52.0/v0.53.0: Engine performance, security hardening, and CEL path functions Authorization Management Platforms: what they do, how they work, and where they fit PocketOS AI coding agent deleted a production database in 9 seconds Non-Human Identity management still has a blind spot Supabase alternative in 2026: Best open source auth options Benefits of on-premise authorization: Why enterprises are moving toward self-hosted Authorization policies: How to write, test, and validate them (faster with AI) Agent skill for writing authorization policies How much does it cost to build authorization in-house? Why centralized authorization governance reduces incident response time OPA alternative Why AI agents make authorization a right now problem Modernizing legacy application authorization: why it’s your biggest security blind spot How to add authorization to legacy applications without code changes 5 authorization blind spots auditors find, and how to fix them
Supercharging your policy rules with self-service custom ...
Sam Lock · 2023-02-07 · via Cerbos - All Posts

A little while ago, we released the blog post: Mapping business requirements to authorization policies. It laid the foundations for how to approach writing your authorization policies from the ground up and discussed different patterns for implementing each.

In this post (the next in a series 👀), we’ll dig a little deeper and look at how to implement a more specific feature: self-service custom roles.

What?

This is a fair response. I mean, we already have all of the flexibility that ABAC gives us - what else do we need?! Well, bear with me, dear reader, whilst I endeavour to explain an approach that might open up even more doors to access-control freedom.

🤔

Consider this scenario: you’re an admin in a multi-tenant system and you want a method by which you can copy an existing role, and then select which permissions/actions to enable or disable for each.

Surely this can’t be achieved with static policies?

Aha! Well, prepare to be adequately surprised. Believe it or not, this approach can absolutely be achieved with static policies. In fact, this is the idiomatic approach to handling these types of scenarios in Cerbos.

Before we dive into an example, let’s provide a little refresher on how access decisions are made in Cerbos:

  • Cerbos is stateless. Your policies and only your policies are baked into the PDP instance.
  • When access control requests are made to Cerbos, the body of the request contains all of the necessary data required to make that decision. This data is freeform - it’s up to the user to decide what’s required and how to structure it.
  • The freeform data can be simple top-level attributes like booleans, integers, floats, and strings, or more complex types, such as arrays, maps, or user defined structs.
  • Cerbos uses this contextual information to make decisions against the defined policies.

A map, you say?

Yes! Maps are great, because by using them, we are no longer constrained to single, static attribute values. Suddenly, we can provide further context (a key in this instance), and our static data becomes a little more dynamic.

Take a look at this example; a resource policy for a resource of type workspace:

apiVersion: "api.cerbos.dev/v1"
resourcePolicy:
  version: "default"
  resource: "workspace"
  rules:
    - actions:
        - workspace:view
        - pii:view
      effect: EFFECT_ALLOW
      roles:
        - USER
      condition:
        match:
          expr: P.attr.workspaces[R.id].role == "OWNER"

Notice how the condition relies on context passed in within the P.attr.workspaces map. The key is the resource ID; the value in this case is a custom struct representing a workspace. Calling the role attribute on that struct returns a predefined value "OWNER".

Now, for our principal, we can provide lots of rich, custom data for each workspace in the organization! These workspaces are constructed from the state in your database of choice, and presented to Cerbos within that single P.attr.workspaces map 👌.

I’m going to need an example!

I got you. Take a look at this; we can grant access to a principal with the USER role, by constructing the following request payload:

cat <<EOF | curl --silent "http://localhost:3592/api/check/resources?pretty" -d @-
{
  "requestId": "quickstart",
  "principal": {
    "id": "123",
    "roles": [
      "USER"
    ],
    "attr": {
      "workspaces": {
        "workspaceA": {
          "role": "OWNER"
        },
        "workspaceB": {
          "role": "MEMBER"
        }
      }
    }
  },
  "resources": [
    {
      "actions": [
        "workspace:view",
        "pii:view"
      ],
      "resource": {
        "id": "workspaceA",
        "kind": "workspace"
      }
    },
    {
      "actions": [
        "workspace:view",
        "pii:view"
      ],
      "resource": {
        "id": "workspaceB",
        "kind": "workspace"
      }
    }
  ]
}
EOF

Here, our principal is trying to carry out workspace:view and pii:view actions on two resources, imaginatively named workspaceA and workspaceB. When building the request, our app consulted our database and constructed the principal attribute data:

    …
    "attr": {
      "workspaces": {
        "workspaceA": {
          "role": "OWNER"
        },
        "workspaceB": {
          "role": "MEMBER"
        }
      }

Cerbos then uses this to make all the decisions for us, et voila 🎉!

Ok, that’s cool and all, but I need to create actual dynamic policies on the fly...

Well, we got you there too 😎. We even wrote an entire blog post about dynamic policy management! But seeing as we’re here, I’ll summarise it again for you.

Firstly, you’re going to need a mutable data store to store your policies. Follow that link, scroll down, and you’ll see the ones that are currently supported by Cerbos. These DBs act as a dynamic store in which Cerbos can add, update and retrieve policies.

As an example, here’s the simplest case – an in-memory instance of SQLite that runs alongside the Cerbos PDP:

storage:
  driver: "sqlite3"
  sqlite3:
    dsn: ":memory:"

There’s every chance that an ephemeral data-store such as the above isn’t going to cut the mustard in your real-life production application, but you get the idea.

OK, so now we have our backing data store, we need to tell Cerbos that it’s allowed to talk to the Admin API. Add (something like) this to your config:

server:
  adminAPI:
    adminCredentials:
      passwordHash: JDJ5JDEwJGJWcFRKUzJKRzYxOTJERWs5SzZaS2VSb2Z1cXNSeTYzam9NR1U5UkVKM3BtZ1VLQUVuM0xlCgo= # passwordHash is the base64-encoded bcrypt hash of the password to use for authentication.
      username: cerbos # Username is the hardcoded username to use for authentication.
    enabled: true # Enabled defines whether the admin API is enabled.

You’ll then have a choice. You can form your own requests and hit the API directly, or alternatively; some of the SDKs have the functionality built in – check out the Go and Javascript examples (we’re continuously improving our library of SDKs so check back for others!).

If you want to see this in action, then check out our full demo. It uses a Go backend and a React client; complete with an editing interface using the Monaco editor.


So there we have it; two wildly different approaches to achieving authorization via powerful, dynamic custom roles in your application. If you have any questions or feedback, head over to our Slack community and introduce yourself!