Параметры в правилах Rego [Open Policy Agent]
Как использовать параметры в правилах 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 небезопасна...
Вообще мне до сих пор непонятно, как передавать параметры в Rego.
1 ответ
Ваш пример почти верен - проблема, с которой вы столкнулись, заключается в том, чтоlabel
"небезопасно".
TL; DR; назначать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"
}
Обратите внимание, я создал ДВА правила запрета. Один для случая, когда путь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
генерирует набор значений (меток?). В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 := ...
}
Это правило гласит (на английском языке):
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" и так будет...)