Перейти к содержимому

Рецепт: политики deny-closed (Cedar / OPA)

Редакция: создание и изменение собственных политик Cedar, включая permit и forbid, требует Business. Community продолжает применять сохранённые политики, пользовательские роли и ограниченные права; чтение и отзыв остаются доступны. DELETE /v1/m/governance/pdp/active?engine=cedar отключает только авторскую политику Cedar и сохраняет историю, управляемые права и принятые политики. Встроенные роли, штатные правила запрета и аварийная остановка остаются в Community. Внешний PDP в этом рецепте только ограничивает доступ; авторские Cedar permit могут предоставлять доступ в пределах своей области. Выбор этого внешнего движка (OLIVARES_PDP_ENGINE, файл Cedar или OPA) требует Business: Community отказывается запускаться, если движок выбран.

Цель: добавить ограничения на основе атрибутов поверх RBAC с deny-by-default — например, «никто не трогает ресурсы с меткой secret, что бы ни говорила его роль».

Один инвариант, который нужно держать в голове: PDP только ограничивает. Решение составляется как RBAC ∩ нативный ABAC ∩ внешний PDP — политика никогда не может выдать то, что отклоняет ролевая модель (модель).

Выберите движок и укажите ему путь к файлу политики, затем перезапустите:

Окно терминала
OLIVARES_PDP_ENGINE=cedar
OLIVARES_PDP_CEDAR_FILE=/etc/olivares/policy.cedar

Политика Cedar — это forbid-наложение: базовый permit означает «RBAC уже принял решение», а ваши правила forbid вычитают:

permit(principal, action, resource);
forbid(principal, action, resource)
when { resource.kind == "credential" && resource.sensitivity == "secret" };

Два факта об авторинге, проверенные по адаптеру: resource.kind и resource.sensitivity всегда присутствуют во входных данных решения (можно ссылаться без условий); любой другой атрибут необходимо защищать через has(), иначе правило не сможет сработать. Написанный вами permit никогда не сможет расширить решение.

Окно терминала
OLIVARES_PDP_ENGINE=opa
OLIVARES_PDP_OPA_URL=http://opa.internal:8181
OLIVARES_PDP_OPA_PATH=/v1/data/olivares/decision
OLIVARES_PDP_OPA_TOKEN=<bearer-reference> # optional

Пишите Rego в режиме permit-by-default:

package olivares
default allow := true
allow := false if {
input.resource.sensitivity == "secret"
endswith(input.permission, ":read")
}

true = нет ограничения. false, отсутствующий результат или любая ошибка транспорта либо ответ не-2xx срабатывают на закрытие (fail closed) — запрос отклоняется, а не остаётся молча неуправляемым.

Модуль governance предоставляет жизненный цикл политики, чтобы плохая политика никогда не попадала вслепую:

Окно терминала
# policy.cedar is the Cedar policy above; jq 1.6 or newer builds the JSON bodies.
# Compile-check the source:
curl -ks -X POST "$BASE/v1/m/governance/pdp/validate" \
-H "Authorization: Bearer $TOKEN" -H "X-Olivares-Tenant: $TENANT" \
-d "$(jq -n --rawfile source policy.cedar '{engine:"cedar",$source}')"
# Pre-flight a decision WITHOUT audit side effects:
curl -ks -X POST "$BASE/v1/m/governance/pdp/dry-run" \
-H "Authorization: Bearer $TOKEN" -H "X-Olivares-Tenant: $TENANT" \
-d "$(jq -n --rawfile source policy.cedar --argjson request '{"principal":{"kind":"user","id":"u1"},"permission":"models:keys:read","resource":{"kind":"credential","sensitivity":"secret"}}' \
'{engine:"cedar",$source,$request}')"
# Then publish (policy-admin permission):
curl -ks -X POST "$BASE/v1/m/governance/pdp/publish" …

GET /v1/m/governance/pdp/versions перечисляет то, что развёрнуто; POST /v1/m/governance/pdp/explain объясняет решение.

  • Перезапуститесь с некорректным файлом политики: движок отключает только внешний PDP и журналирует это — RBAC и нативный ABAC продолжают управлять; control plane не падает.
  • Каждое ограничение, которое применяет PDP, аудируется — проверьте ledger после отклонённого запроса.
  • Политики версионируются и публикуются, а не редактируются «на лету» в продакшене — относитесь к публикации как к изменению, прошедшему ревью.
  • Для действий, требующих одобрения (а не отклонения), смотрите одобрения HITL.