Matthew Ebeweber
09/29/2022, 5:54 PMmatch:
any:
of:
- expr: V.foo
- expr: V.bar
vs.
match:
expr: V.foo || V.bar
Charith (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)
_ = true
Matthew Ebeweber
09/30/2022, 2:21 PM