Агент открытой политики - явное логическое И в конвейере CI

Я пытаюсь написать политику, которая регулирует совместимость имени пользователя администратора, которая состоит из трех правил: буквенно-цифрового значения, а не части запрещенных имен (администратор, администратор и т. Д.) И длиннее 5 символов.

Я обнаружил, что при использовании OPA как части конвейера CI (что является моим вариантом использования) наиболее удобным решением является создание объекта (словаря), который содержит результаты политики, чтобы я мог напрямую запрашивать их. Моя строка внутри конвейера CI будет выглядеть так:

for file in rego_directory:
     opa eval -i file -d data.json "package_name.policy"

Что не выводит на печать все переменные и временные ресурсы, которые я использую внутри файла rego (что сохраняет много журналов и выходных данных). Чтобы создать этот объект "политики", у меня есть в моем rego-файле следующий шаблон:

policy[policy_name] = result {
    policy_name := 
    ...
    computations...
    ...
    result := <logical condition>
}

Теперь мои вопросы следующие: Мне это не кажется лучшей практикой. Есть ли другой способ просто исключить переменные из вывода? раньше я работал с отдельными значениями (т.е. примерно так:

default policy_1 = false
default policy_2 = false

policy_1 = {
    <logical condition>
}
policy_2 = {
    <logical condition>
}

Второй вопрос: как мне создать выходной словарь (поскольку выходные данные словаря в формате JSON - это хороший формат для работы, в конце концов), который может удовлетворять нескольким условиям? оглядываясь на свой пример, я не могу написать что-то вроде этого:

policy[policy_name] = result {
    policy_name := 
    ...
    computations...
    ...
    result := <logical condition>
    result := <logical condition 2>
}

Поскольку это двойное присвоение, которое недопустимо. Даже если я использую= вместо того :=, это создает конфликты, если один термин истинен, а другой ложен, а ошибки - это не то, что я ищу (мне нужны логические ответы). Как мне создать сложное правило, вывод которого я могу поместить в этот словарь?

Заранее спасибо.

1 ответ

TL; DR; чтобы прямо ответить на ваши вопросы:

Теперь мои вопросы следующие: Мне это не кажется лучшей практикой. Есть ли другой способ просто исключить переменные из вывода?

Нет ничего плохого в том, чтобы ваше программное обеспечение запрашивало значение, сгенерированное каким-либо правилом. Фактически, правила - это фундаментальный способ определения абстракций в ваших политиках, так что вы можете отделить принятие решений по политике (т. Е. Логику, которая вырабатывает решение) от применения политики (т. Е. Логики / действий, предпринятых на основе решения по политике.)

Единственная реальная альтернатива - запросить набор правил внутри одного или нескольких пакетов, как вы показали.

Второй вопрос: как мне создать выходной словарь (поскольку выходные данные словаря в формате JSON - это хороший формат для работы, в конце концов), который может удовлетворять нескольким условиям? оглядываясь на свой пример, я не могу написать что-то вроде этого:

Вы спрашиваете, как выразить логическое ИЛИ. В этом случае вы должны создать несколько определений (в некоторых местах мы называем их "инкрементными определениями")policy правило:

policy[policy_name] = result {
    policy_name := 
    ...
    computations...
    ...
    result := <logical condition>
}

policy[policy_name2] = result2 {
    policy_name2 := 
    ...
    some other computations...
    ...
    result2 := <some other logical condition>
}

Этот фрагмент определяет объект (с именем policy), который отображает policy_name к result а также policy_name2 к result2. Мы называем это правило частичным объектом. Вы также можете определить частичные наборы. При определении частичного объекта необходимо убедиться, что каждый ключ соответствует не более чем одному значению (в противном случае вы получите ошибку времени выполнения).

Другим способом структурирования вашей политики было бы (по сути) определение списка запретов с использованием частичных наборов:

package usernames

deny["username must use alphanumeric characters"] {
  re_match("[a-zA-Z0-9]", input.username)
}

deny["username must be at least 5 characters long"] {
  count(input.username) < 5
}

deny["username is reserved"] {
  reserved_usernames[input.username]
}

reserved_usernames := {"admin", "root"}

Тогда ваш конвейер CI может просто запросить deny:

opa eval -i input.json 'data.usernames.deny'

Результат будет содержать причины, по которым имя пользователя не должно быть разрешено.

Другие вопросы по тегам