Matthew Ebeweber
09/29/2022, 5:54 PMmatch:
any:
of:
- expr: V.foo
- expr: V.bar
vs.
match:
expr: V.foo || V.barCharith (Cerbos)
|| operator does not short-circuit whereas anyOf does. I don't see how that would affect the result of these expressions though. What are the definitions of V.bar and V.foo?Matthew Ebeweber
09/29/2022, 6:42 PMisScoped: P.attr.scopedTenantQid != ''
isUnscoped: |-
P.attr.scopedTenantQid == ''
isScopedToCorpTenant: |-
P.attr.isCorpTenant && P.attr.tenantQid == P.attr.scopedTenantQid
They look like this where isCorpTenant is a boolean and fooQid variables are a string (empty or with a value).Charith (Cerbos)
any block fails to evaluate or returns a non-boolean value, we stop evaluating the rest of the expressions in the block and return false immediately. I think that's probably what you have seen. It's likely that V.foo returns a non-boolean value because one of the attributes used to calculate it returns a null. I ran a test with a principal that didn't have the scopedTenantQid attribute and got the following trace:
policy=cerbos.resource.TEST.vdefault > scope="" > variables > isUnscoped=`P.attr.scopedTenantQid == ''`
activated
result → null
policy=cerbos.resource.TEST.vdefault > scope="" > variables > isUnscoped=`P.attr.scopedTenantQid == ''`
activated
result → null
policy=cerbos.resource.TEST.vdefault > scope="" > variables > isUnscoped=`P.attr.scopedTenantQid == ''`
activated
result → null
policy=cerbos.resource.TEST.vdefault > scope="" > rule=rule-002 > action=B > condition > conditionAny > condition#0 > expr=`V.isScoped`
activated
result → false
Failed to evaluate expression: unexpected result: wanted bool, got structpb.NullValue
policy=cerbos.resource.TEST.vdefault > scope="" > rule=rule-002 > action=B > condition > conditionAny
activated
result → false
Short-circuited: failed to evaluate `V.isScoped`: unexpected result: wanted bool, got structpb.NullValue
policy=cerbos.resource.TEST.vdefault > scope="" > rule=rule-002 > action=B
skipped
Error evaluating condition: failed to evaluate `V.isScoped`: unexpected result: wanted bool, got structpb.NullValue
If scopedTenantQid doesn't exist, scopedTenantQid == '' evaluates to null and it's not a boolean, so Cerbos gives up checking the rest because it thinks there's an error in the expression and it's safer to fail than carry on.Charith (Cerbos)
false values. But, there might be other unintended consequences of that so it needs a bit more pondering. In the mean time, using schemas to enforce required attributes could help catch problems like this early.Matthew Ebeweber
09/30/2022, 2:05 PMMatthew Ebeweber
09/30/2022, 2:14 PMP.attr.foo . If foo isn't present I want to the system to ignore that rule for now (avoid updating every test or weird permission issues during a deploy).
Adding a P.attr.foo == null doesn't seem to do the trick.Matthew Ebeweber
09/30/2022, 2:18 PMCharith (Cerbos)
has(P.attr.foo) to check whether foo existsCharith (Cerbos)
-> :let x = {"y": "z"}
x = {
"y": "z"
}
-> has(x.x)
_ = false
-> has(x.y)
_ = trueMatthew Ebeweber
09/30/2022, 2:21 PM