Ваш пример почти правильный - проблема, с которой вы сталкиваетесь, заключается в том, что label
является "небезопасным".
TLDR; назначьте 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 генерирует ошибку безопасности в исходном примере? Безопасность - это свойство Re go, которое гарантирует, что всем переменным может быть присвоено конечное число значений. Чтобы считаться «безопасной», переменная должна появляться как результат хотя бы одного неотрицательного выражения.
Вот несколько примеров, которые все безопасны:
# '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 := ...
}
Это правило гласит (на английском языке sh):
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" и так будет ...)