Open Policy Agent如何验证数组所有元素满足指定字段存在条件?
如何用Rego验证数组中所有对象都存在指定字段
我完全懂你的困扰——在做云资源标签这类必须100%合规的校验时,Rego默认的“存在即真”逻辑确实容易让人踩坑。你之前用的input.array.foo其实是在提取数组中所有对象的foo值,只要有一个对象包含这个字段,表达式就会返回非空集合,在规则中被判定为true,根本不会检查全量是否满足。
下面给你两种可行的解决方案,都能实现“数组中所有对象必须存在foo字段”的校验,并且触发你需要的var_is_unsafe错误:
方法1:用every关键字遍历校验(推荐)
every是Rego专门用来做全量遍历校验的关键字,逻辑清晰且易读,非常适合这类场景:
# 校验所有对象都存在foo字段 all_have_foo_field { every obj in input.array { exists(obj.foo) # 严格检查字段是否存在,即使值为空也视为合规 } } # 当校验不通过时触发错误 var_is_unsafe { not all_have_foo_field }
逻辑说明:
every obj in input.array会迭代数组中的每一个对象exists(obj.foo)专门用来判断字段是否存在(区别于obj.foo会同时检查值的真实性):只要对象里有foo这个键,不管值是空字符串还是null,都会返回true;如果完全没有这个键,就返回false- 只有当所有对象都通过
exists(obj.foo)的检查,all_have_foo_field才会为true;反之,只要有一个对象缺失foo字段,not all_have_foo_field就会成立,触发var_is_unsafe
方法2:用数组推导式对比数量
如果你更习惯用集合操作的思路,也可以通过对比“包含foo字段的对象数量”和“数组总长度”来实现校验:
# 校验所有对象都存在foo字段 all_have_foo_field { # 原数组长度 == 包含foo字段的对象数量 count(input.array) == count([obj | obj := input.array[_]; exists(obj.foo)]) } # 触发错误的规则 var_is_unsafe { not all_have_foo_field }
逻辑说明:
[obj | obj := input.array[_]; exists(obj.foo)]是Rego的数组推导式,会生成一个新数组,只包含原数组中存在foo字段的对象- 对比新数组和原数组的长度,如果相等,说明所有对象都符合要求;只要有一个对象缺失
foo,长度就会不一致,触发错误
额外提示
如果你的场景不仅要求字段存在,还需要foo字段有非空有效值,可以把exists(obj.foo)改成obj.foo != ""(针对字符串)或者obj.foo(Rego中,非空字符串、非0数字、非空集合都会被视为true),根据实际需求调整即可。
内容的提问来源于stack exchange,提问作者FitzChivalry
相关产品推荐
相关产品推荐

