如何控制Open Policy Agent(OPA)响应,仅保留allow与permissions字段
限制OPA响应仅返回指定字段的方法
问题说明
现有Open Policy Agent(OPA)策略运行正常,但返回响应包含冗余字段(如read、write、approve这类用于构建permissions的辅助规则结果),需将响应限制为仅保留allow和permissions两个字段。
原策略代码
package example default allow = false getUserPermissions(user) = userpermission { allowed_list := {"users": { "a": {"permissions": [ "app.write", "app.approve", "app.read", ]}, "b": {"permissions": [ "app.write", "app.read", ]}, }} userpermission = allowed_list.users[user].permissions } has_any_privilege(x_arr) { uid := input.user permissions := getUserPermissions(uid) permissions[_] == x_arr[_] } default approve = false approve { has_any_privilege({"app.approve"}) } default write = false write { has_any_privilege({"app.write"}) } default read = false read { has_any_privilege({"app.read", "app.write", "app.approve"}) } allow { has_any_privilege({"app.read"}) } permissions := { "approve": approve, "write": write, "read": read, }
输入示例
{"user": "b"}
当前冗余响应
{ "allow": true, "approve": false, "permissions": { "approve": false, "read": true, "write": true }, "read": true, "write": true }
解决方法
方法1:查询阶段筛选字段
调用OPA时,直接指定要获取的目标字段,而非查询整个包。使用以下查询语句:
data.example.allow, data.example.permissions
或JSON格式的查询参数:
{"query": "data.example.allow, data.example.permissions"}
此方法无需修改策略,通过查询语法直接过滤结果,返回的响应仅包含allow和permissions字段。
方法2:策略内封装结果并隐藏辅助规则
修改策略,将所有辅助规则标记为私有(规则名前加下划线_),避免其出现在响应中;同时新增顶层规则封装需要返回的字段:
修改后的策略代码:
package example default allow = false # 私有辅助规则,不会暴露到响应中 _getUserPermissions(user) = userpermission { allowed_list := {"users": { "a": {"permissions": [ "app.write", "app.approve", "app.read", ]}, "b": {"permissions": [ "app.write", "app.read", ]}, }} userpermission = allowed_list.users[user].permissions } # 私有辅助规则 _has_any_privilege(x_arr) { uid := input.user permissions := _getUserPermissions(uid) permissions[_] == x_arr[_] } # 私有辅助规则 default _approve = false _approve { _has_any_privilege({"app.approve"}) } # 私有辅助规则 default _write = false _write { _has_any_privilege({"app.write"}) } # 私有辅助规则 default _read = false _read { _has_any_privilege({"app.read", "app.write", "app.approve"}) } allow { _has_any_privilege({"app.read"}) } permissions := { "approve": _approve, "write": _write, "read": _read, } # 封装最终返回结果 result := { "allow": allow, "permissions": permissions }
查询data.example.result即可得到干净的响应:
{ "result": { "allow": true, "permissions": { "approve": false, "read": true, "write": true } } }
内容的提问来源于stack exchange,提问作者Ahmed Ayoub
相关产品推荐
相关产品推荐

