Rego规则中的参数[开放策略代理]

kal*_*ise 1 open-policy-agent rego

如何在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]
}
Run Code Online (Sandbox Code Playgroud)

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

总的来说,我还是不太清楚如何在Rego中传递参数。

tsa*_*all 7

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

太长了;label在规则内分配deny

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"
}
Run Code Online (Sandbox Code Playgroud)

请注意,我创建了两个拒绝规则。一种用于路径未定义的情况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]
Run Code Online (Sandbox Code Playgroud)

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

# '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)
Run Code Online (Sandbox Code Playgroud)

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

# 'msg' is unsafe because it is not assigned inside the body of the rule.
deny[msg] {
  input.request.kind.kind == "BadKind"
}
Run Code Online (Sandbox Code Playgroud)

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

deny[reason] {
  some label
  input.request.kind.kind == "Route"
  not valid_route_request[label]
  reason := ...
}
Run Code Online (Sandbox Code Playgroud)

这条规则说(英文):

reason is in deny if for some label, input.request.kind.kind equals Route and label is not in valid_route_request, and ...
Run Code Online (Sandbox Code Playgroud)

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