使用嵌套对象时如何 return rego 响应中每个对象的错误消息

How to return error messages per object in rego response when using nested objects

我正在创建一个策略来验证对记录集合的访问。这些记录作为输入传递,并附加了一组权限。我根据存储在 OPA 中的权限数据验证它们。

例如,我可以 return 通过执行类似操作可以访问的记录集合

isAllowed[id] {
   permissionSet := {x | x := permissions.groups[_].name}
   id := input.records[i].id
   input.operation == "update"
   input.records[i].acls.owners[j]==permissionSet[k]
}{
   id := input.records[i].id
   input.operation == "create" }

哪个会 return 像

"isAllowed": ["123"]

当输入如下并且'permissions'数据包含“service.legal.user”

  "input": { 
        "operation": "update", 
        "records": [
            { "id": "123", "acls": { "owners": ["service.legal.user"] }},
            { "id": "456", "acls": { "owners": ["service.storage.viewer"] }}
        ]
   }

但是我想要return像下面这样的东西,我列出所有输入记录并将错误消息分配给失败的所有记录

"records":[
   {"id": "123", "errors": ""}, 
   {"id": "456", "errors": "You must have owner permission to update a record"}
]

我尝试了增量规则,但我从 OPA 收到了错误消息 'complete rules must not produce multiple outputs'

isAllowed = response {
    #owner permission checked for update operation on all records
    some i
    response := {
      "id" : input.records[i].id,
      "errors" : CheckErrors
    }
}
CheckErrors[reason] {
    reason := "Must be an owner to update a record"
    input.operation == "update"
    permissionSet := {x | x := permissions.groups[_].name}
    input.records[i].acls.owners[j]==permissionSet[k]
}
CheckErrors[reason]{
    #no permission checked for create operation on all records
    reason := "Anyone can create"
    input.operation == "create"
}

欢迎任何帮助。

不确定我是否完全遵循,并且您没有提供权限对象,但假设 groups 只是像 {"name": "service.legal.user"} 这样的对象列表,如下所示的内容会产生您想要的输出。

records[response] {    
    id := input.records[_].id
    errors := [r | e := check_errors[_]
                   e.id == id
                   r := e.reason]
    
    response := {
        "id" : id,
        "errors" : errors
    }
}

check_errors[{"id": id, "reason": "Must be an owner to update a record"}] {
    input.operation == "update"
    id := input.records[x].id
    permissionSet := {x | x := permissions.groups[_].name}
    owners := {o | o := input.records[x].acls.owners[_]}
    
    count(owners & permissionSet) == 0
}

完整示例 here.