I am getting an error when using the PlanResources...
# help
I am getting an error when using the PlanResources API that does not occur when I use the CheckResources API. It seems like it is a bug, but wanted some guidance in case I am doing something wrong I’ve determined that it is due to my Derived Roles, specifically
location_roles: P.attr.roles[R.attr.location_id]
If I hard code this to `location_roles: P.attr.roles["1"]`everything seems to work as expected.
Copy code
apiVersion: api.cerbos.dev/v1
  location_roles: P.attr.roles[R.attr.location_id]
  name: my_roles
    - name: global_admin
        - user
          expr: ("Global Admin" in V.location_roles)
Copy code
{"log.level":"info","@timestamp":"2022-11-07T23:34:00.201Z","log.logger":"cerbos.payload","message":"server request payload logged as grpc.request.content field","system":"grpc","span.kind":"server","grpc.service":"cerbos.svc.v1.CerbosService","grpc.method":"PlanResources","peer.address":"","http":{"x_forwarded_for":[""],"x_forwarded_host":["localhost:3592"]},"grpc.request.content":{"msg":{"action":"entry:read","principal":{"id":"1","policyVersion":"default","roles":["user"],"attr":{"employee_id":"123","permissions":{"1":["entry.read_all"]},"roles":{"1":["Employee"]}}},"resource":{"kind":"entry","attr":{"location_id":"1"},"policyVersion":"default"},"includeMeta":true}}}
{"log.level":"error","@timestamp":"2022-11-07T23:34:00.203Z","log.logger":"cerbos.grpc","message":"Resources query plan request failed","grpc.start_time":"2022-11-07T23:34:00Z","system":"grpc","span.kind":"server","grpc.service":"cerbos.svc.v1.CerbosService","grpc.method":"PlanResources","peer.address":"","http":{"x_forwarded_for":[""],"x_forwarded_host":["localhost:3592"]},"cerbos":{"call_id":"01GHA734RAWRPKZD2E4NGASBH1"},"error":"error evaluating condition \"(\\\"Employee\\\" in V.location_roles)\": invalid qualifier type: *structpb.Value"}
{"log.level":"error","@timestamp":"2022-11-07T23:34:00.203Z","log.logger":"cerbos.grpc","message":"Handled request","grpc.start_time":"2022-11-07T23:34:00Z","system":"grpc","span.kind":"server","grpc.service":"cerbos.svc.v1.CerbosService","grpc.method":"PlanResources","cerbos":{"call_id":"01GHA734RAWRPKZD2E4NGASBH1"},"peer.address":"","http":{"x_forwarded_for":[""],"x_forwarded_host":["localhost:3592"]},"error":"rpc error: code = Internal desc = Resources query plan request failed","grpc.code":"Internal","grpc.time_ms":2.047}
This looks like a bug. Thanks for reporting it. But even if the call succeeded, the produced AST would be complex. I’d suggest another way to write the expression.
I’ll post the alternative expression in a few minutes.
Cool thanks, I was also wondering if I was overcomplicating things. Basically trying to model multiple roles in a multi-tenant system with support for custom roles
Something like:
R.attr.location_id in P.attr.roles.filter(x, P.attr.roles[x].exists(y, y == "Global Admin"))
In the above expression the RHS can be pre-evaluated, so the produced AST can be simple
R.attr.location_id in [<list of constants>]
Are there any resources available that describe “the right way” to design policies?
Well, I’d say your policy is written in a very neat and idiomatic way. It is the query planner that introduces some nuances. Ideally, it should be smart enough to produce the
R.attr.location_id in <list of constants>
. If your question is more general, there’s a tutorial https://docs.cerbos.dev/cerbos/latest/tutorial/00_intro.html that gives an example of how to design the policy.
gotcha, I guess I was wondering how you just looked at my policy and then knew the query planner would produce a complex AST. If there were any guidance on what to avoid
Generally, the AST looks complex when
are both present in the struct indexing expression like in your
My trick was to separate them into subexpressions.
ah, super helpful, thanks!
I’ve created an issue to track the bug
I can’t reproduce the original problem with Cerbos v0.22.0, which we have just released. Can you please try the latest version if you haven’t yet?
I was reproducing with 0.22 I will get you a repro case
Repro attached to the issue, assuming playground is running 0.22.0
Thank you!
I didn’t notice at first that the request contains the resource attribute location_id equal “1”. The query planner takes all known attributes into account, so the response should be unconditional “KIND_ALWAYS_ALLOWED”. It gives an error instead…