跳转到内容

实战手册:默认拒绝(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 拒绝启动。

目标: 在默认拒绝(deny-by-default)的 RBAC 之上叠加基于属性的限制—— 例如,“无论角色如何规定,任何人都不能触碰标记为 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

按 默认放行(permit-by-default) 编写 Rego:

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

true = 不做限制。false、缺失的结果,或 任何传输错误或非 2xx 错误都会失败关闭 (fail closed)——请求被拒绝,绝不会悄无声息地处于不受治理的状态。

治理模块暴露了一套策略生命周期,使得有问题的策略绝不会盲目上线:

终端窗口
# 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 审批。