Benjamin Rupp
06/26/2025, 3:38 PMBenjamin Rupp
06/26/2025, 3:39 PM{
"apiVersion": "api.cerbos.dev/v1",
"resourcePolicy": {
"version": "default",
"resource": "/api/v1/stitchit/objects/query",
"rules": [
{
"actions": [
"post"
],
"effect": "EFFECT_ALLOW",
"name": "post.api.v1.stitchit.objects.query",
"roles": [
"inventory_read"
]
}
]
}
}
Which allows a user with inventory_read
role to access this endpoint. These resource policies are static and should not change between releases.
Now we want to restrict certain user's access to inventory objects, based on metadata provisioned on those objects. Metadata being key value pairs, such as city=Amsterdam
For this, we use role policies, which can be changing frequently:
"rolePolicy": {
"role": "berlin",
"parentRoles": [
"inventory_read"
],
"scope": "d95e67fc-64b5-4869-82bb-120b69424130.data",
"rules": [
{
"resource": "*",
"allowActions": [
"*"
],
"condition": {
"match": {
"all": {
"of": [
{
"expr": "request.resource.attr.city in [\"berlin\"]"
}
]
}
}
}
}
]
}
The role policy makes it so that my user with role berlin
(IdP role) now has access to the endpoint /api/v1/stitchit/objects/query
with action post
and condition city=berlin
Here is a request
curl <http://localhost:3592/api/plan/resources> -d '{
"requestId": "test01",
"action": "post",
"resource": {
"policyVersion": "default",
"kind": "/api/v1/stitchit/objects/query",
"scope": "d95e67fc-64b5-4869-82bb-120b69424130.data"
},
"principal": {
"id": "Ben",
"roles": ["berlin"]
},
"includeMeta": true
}'
And the response
{
"requestId": "test01",
"action": "post",
"resourceKind": "/api/v1/stitchit/objects/query",
"policyVersion": "default",
"filter": {
"kind": "KIND_CONDITIONAL",
"condition": {
"expression": {
"operator": "eq",
"operands": [
{
"variable": "request.resource.attr.city"
},
{
"value": "berlin"
}
]
}
}
},
"meta": {
"filterDebug": "(eq request.resource.attr.city \"berlin\")"
},
"cerbosCallId": "01JYPBWCX841QY2ZB1H6EZQVBT"
}
👍 This is perfect and exactly what we want.Benjamin Rupp
06/26/2025, 3:39 PM{
"apiVersion": "api.cerbos.dev/v1",
"resourcePolicy": {
"version": "default",
"resource": "/api/v1/stitchit/objects/query",
"rules": [
{
"actions": [
"post"
],
"effect": "EFFECT_ALLOW",
"name": "post.api.v1.stitchit.objects.query",
"roles": [
"inventory_read",
"contributor"
]
}
]
}
}
And I sent in the principal
also with this contributor role
curl <http://localhost:3592/api/plan/resources> -d '{
"requestId": "test01",
"action": "post",
"resource": {
"policyVersion": "default",
"kind": "/api/v1/stitchit/objects/query",
"scope": "d95e67fc-64b5-4869-82bb-120b69424130.data"
},
"principal": {
"id": "Ben",
"roles": ["berlin", "contributor"]
},
"includeMeta": true
}'
Now I get: KIND_ALWAYS_ALLOWED
It is logical to me: Because I have the contributor role, which is directly authorized by the resourcePolicy, my role policy berlin
is not evaluated.
My question is: Is there a way where I can still have the berlin
role policy evaluated and the conditional returned? Some configuration option, or maybe a different provisioning approach?
We are facing this issue, because we have to deal with legacy roles and backwards compatibility.
Thank you in advanceBenjamin Rupp
06/26/2025, 3:58 PMlenientScopeSearch: true
and Cerbos 0.45.0Dennis (Cerbos)
berlin
role policy evaluated and the conditional returned? Some configuration option, or maybe a different provisioning approach?
Do you expect the output to be like true && R.attr.city == "berlin"
or simply R.attr.city == "berlin"
?
• If the former, it’s not possible since the query planner short-circuits evaluation and further “normalises” the output.
• If you meant the latter, the contributor must not be a “normal” role, but a role designated by a role policy.Billy Bolton
07/03/2025, 3:16 PM• If you meant the latter, the contributor must not be a “normal” role, but a role designated by a role policy.Yes, we are hoping for the latter. I'm not clear however what you mean by "normal" role
Billy Bolton
07/03/2025, 7:53 PMdeny
rules when a principal had multiple roles. This could lead to overly restrictive query plans.
> Consider a principal who is both an admin
(with broad allow
rules) and a viewer
(with more specific deny
rules). The admin
role's permissions should take precedence. The query planner now correctly prioritizes the role(s) that grant access, ensuring the generated plan is not unnecessarily constrained by lower-privileged roles.
In our example above, we need the roles with more restrictions to be prioritized since the "contributor" role won't have any rules set, even as its own proper role policy
We really hope this is possibleDennis (Cerbos)
Billy Bolton
07/03/2025, 9:20 PMBilly Bolton
07/03/2025, 9:50 PMcurl -X POST -k -u cerbos:cerbosAdmin '<http://localhost:3592/admin/policy>' -d '{
"policies": [
{
"apiVersion": "api.cerbos.dev/v1",
"resourcePolicy": {
"version": "default",
"resource": "/api/v1/stitchit/objects/query",
"rules": [
{
"actions": [
"post"
],
"effect": "EFFECT_ALLOW",
"name": "post.api.v1.stitchit.objects.query",
"roles": [
"inventory_read",
"contributor"
]
}
]
}
},
{
"apiVersion": "api.cerbos.dev/v1",
"rolePolicy": {
"role": "berlin",
"parentRoles": [
"inventory_read"
],
"rules": [
{
"resource": "*",
"allowActions": [
"*"
],
"condition": {
"match": {
"all": {
"of": [
{
"expr": "request.resource.attr.city in [\"berlin\"]"
}
]
}
}
}
}
]
}
},
{
"apiVersion": "api.cerbos.dev/v1",
"rolePolicy": {
"role": "contributor",
"rules": [
{
"resource": "*",
"allowActions": [
"*"
]
}
]
}
}
]
}
'
curl <http://localhost:3592/api/plan/resources> -d '{
"requestId": "test01",
"action": "post",
"resource": {
"policyVersion": "default",
"kind": "/api/v1/stitchit/objects/query"
},
"principal": {
"id": "Ben",
"roles": ["berlin","contributor"]
},
"includeMeta": true
}'
{
"requestId": "test01",
"action": "post",
"resourceKind": "/api/v1/stitchit/objects/query",
"policyVersion": "default",
"filter": {
"kind": "KIND_ALWAYS_ALLOWED"
},
"meta": {
"filterDebug": "(true)"
},
"cerbosCallId": "01JZ940P86W09CVTSWWKNGSGFW"
}
I recognize this behaviour is "correct and by design" but we really we need a way to prioritize more restrictive roles (ie. berlin
). Is there maybe a rule condition we can set on the resource policy somehow that "if this role do this", sort of thing?Dennis (Cerbos)
"resourcePolicy": {
"version": "default",
"resource": "/api/v1/stitchit/objects/query",
"rules": [
{
"actions": [
"post"
],
"effect": "EFFECT_ALLOW",
"name": "post.api.v1.stitchit.objects.query",
"roles": [
"inventory_read",
"contributor"
]
}
]
}
The “contributor” is listed the resourcePolicyDennis (Cerbos)
Dennis (Cerbos)
"allowActions": ["*"]
had "allowAction: ["read"]
, what do you expect from the request with action “post” and roles [“berlin”, “contributor”]? Unconditionally allowed?Billy Bolton
07/03/2025, 11:12 PMKIND_ALWAYS_ALLOWED
because the berlin
role would no longer have a matching resource/*action*, and I'd expect it to fall back to the contributor
role that does.
If you do raise an issue that's externally visible, we would be grateful to follow-along to track how it might be resolved.Billy Bolton
07/03/2025, 11:49 PMDennis (Cerbos)
Billy Bolton
07/03/2025, 11:52 PMDennis (Cerbos)
Dennis (Cerbos)
Billy Bolton
07/04/2025, 12:17 AMDennis (Cerbos)
Billy Bolton
07/04/2025, 12:28 AMDennis (Cerbos)
Billy Bolton
07/04/2025, 12:37 AMDennis (Cerbos)
Billy Bolton
07/04/2025, 10:28 AM