Параметры в правилах Re go [Open Policy Agent] - PullRequest
0 голосов
/ 03 мая 2020

Как использовать параметры в правилах Re go? У меня было бы что-то вроде этого:

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 небезопасна ...

Вообще говоря, мне все еще не ясно, как передать параметры в Re go.

1 Ответ

2 голосов
/ 05 мая 2020

Ваш пример почти правильный - проблема, с которой вы сталкиваетесь, заключается в том, что 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 не назначен где-либо еще в правиле denylabel, по-видимому, не отображается в глобальной области видимости). Это на самом деле становится немного понятнее, если вы включите '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" и так будет ...)

...