Rego 规则中的参数 [Open Policy Agent]

Posted

技术标签:

【中文标题】Rego 规则中的参数 [Open Policy Agent]【英文标题】:Parameters in Rego rules [Open Policy Agent] 【发布时间】:2020-05-03 17:15:01 【问题描述】:

如何在 Rego 规则中使用参数?我会有这样的东西:

deny[reason] 
  input.request.kind.kind == "Route"
  not valid_route_request[label]
  reason := sprintf("missing or wrong router selector label: %v", [label])


valid_route_request[label] 
  requester := input.request.userInfo.username
  some i # iterate on all users
  requester == data.kubernetes.users[i].metadata.name
  label := input.request.object.metadata.labels["router-selector"]
  label == data.kubernetes.users[i].metadata.annotations[router_selector_key]

其中label 用于构建错误消息。我从 OPA 收到错误:var label is unsafe ...

一般来说,我仍然不清楚如何在 Rego 中传递参数。

【问题讨论】:

【参考方案1】:

您的示例几乎是正确的——您面临的问题是label 是“不安全的”。

TLDR;在deny 规则中分配label

deny[reason] 
    input.request.kind.kind == "Route"
    label := input.request.object.metadata.labels["router-selector"]
    not valid_route_request[label]
    reason := sprintf("wrong 'router-selector' label: %v", [label])


deny[reason] 
    input.request.kind.kind == "Route"
    not input.request.object.metadata.labels["router-selector"]
    reason := "missing 'router-selector' label"

注意,我创建了两个拒绝规则。一种用于路径input.request.object.metadata.labels["route-selector'] 未定义,另一种用于无效值的情况。

为什么 OPA 会在原始示例中生成安全错误?安全性是 Rego 的一个属性,它确保可以为所有变量分配有限数量的值。要被认为是“安全的”,变量必须作为至少一个非否定表达式的输出出现。

以下是一些安全的示例:

# 'a' is assigned to the value referenced by input.foo
a := input.foo

# 'x' is assigned to the keys of the collection referenced by input.foo
input.foo[x]

# 'label' is is assigned to the keys of the collection referenced by valid_route_request
valid_route_request[label]

# 'x' is safe because it is assigned outside the negated expression
x := 7; not illegal_numbers[x]

以下是不安全表达式的示例:

# 'x' is unsafe because it does not appear as an output of a non-negated expression
not p[x]; not q[x]


# 'y' is unsafe because it only appears as a built-in function input
count(y)

规则头部出现的变量也可能发生安全错误:

# 'msg' is unsafe because it is not assigned inside the body of the rule.
deny[msg] 
  input.request.kind.kind == "BadKind"

安全性很重要,因为它确保 OPA 可以枚举所有可以分配给变量的值。如果变量不安全,则意味着可能有无限数量的变量赋值。在您的示例中,语句 valid_route_request 生成一组值(标签?)。 deny 规则中的 not valid_route_request[label] 语句是不安全的,因为 label 未在 deny 规则的其他位置分配(并且 label 可能不会出现在全局范围内。)在拒绝规则中包含“一些”:

deny[reason] 
  some label
  input.request.kind.kind == "Route"
  not valid_route_request[label]
  reason := ...

这条规则说(英文):

reason is in deny if for some label, input.request.kind.kind equals Route and label is not in valid_route_request, and ...

从技术上讲,满足此规则的label 的分配数量将无限多(例如,字符串“12345”不会包含在valid_route_request 中,“123456”也不会包含...)

【讨论】:

以上是关于Rego 规则中的参数 [Open Policy Agent]的主要内容,如果未能解决你的问题,请参考以下文章

检查数组是不是包含在 rego 中的另一个中

如何定制 Calico 网络 Policy - 每天5分钟玩转 Docker 容器技术(70)

Open Policy Agent - 提高分组理解的性能

开放策略代理 (OPA) Rego - 在运行时访问输入对象嵌套字段

使用 walk 以 rego 递归聚合 terraform 状态下的资源

云原生策略引擎 OPA 介绍