sync a58faaa refactor(authz)

This commit is contained in:
2026-10-13 18:28:09 +07:00
parent 5519ae2de7
commit 678885f681
6 changed files with 290 additions and 40 deletions
+1
View File
@@ -29,6 +29,7 @@ MODEL OPA (authz.yml -> data.json):
matrix [--schema <s>] matriks role x tabel (s=select w=write d=ddl)
show role|user|table <nama> detail satu objek
grant add|set|remove <role> <schema.table> [--caps a,b] [--columns x,y|*]
grant add <role> '<schema>.*' [--caps a,b] # seluruh tabel di schema (mis. gold.*)
role add|remove <nama> [--superuser] [--force]
user assign|unassign <svc> <role> service account -> role (model)
catalog list|add|rename <baru> kelola catalog (rename ikut berkas Trino)
+47 -3
View File
@@ -55,10 +55,10 @@ then ok "data.json identik dengan hasil render"; else bad "data.json berbeda dar
# ─── B. Policy data-driven ───────────────────────────────────────────────────
echo; echo -e "${BLD}B. Policy Rego data-driven${NC}"
if grep -q 'data.authz.catalogs' "${REGO}" && grep -q 'data.authz.write_schemas' "${REGO}"; then
ok "Rego membaca katalog/schema dari data.authz.*"
if grep -q 'data.authz.catalogs' "${REGO}" && grep -q 'schema_grant' "${REGO}"; then
ok "Rego data-driven (data.authz.catalogs + schema_grant)"
else
bad "Rego belum data-driven (data.authz.* tidak ditemukan)"
bad "Rego belum data-driven (data.authz.* / schema_grant tidak ditemukan)"
fi
if grep -qE '"iceberg"' "${REGO}"; then
bad "Rego masih meng-hardcode literal \"iceberg\""
@@ -86,6 +86,19 @@ case "${out}" in *"caps=[select,write]"*) ok "grant set menimpa caps" ;; *) bad
out="$(cli show role data-scientist)"
case "${out}" in *"caps=[select]"*) ok "grant remove --caps menyisakan select" ;; *) bad "grant remove gagal: ${out}" ;; esac
"${CLI}" --model "${M}" grant add data-scientist 'gold.*' --caps select --columns "*" >/dev/null 2>&1
out="$(cli show role data-scientist)"
case "${out}" in *"gold.*"*) ok "grant tingkat-schema tersimpan (gold.*)" ;; *) bad "grant schema tak tersimpan: ${out}" ;; esac
python3 "${DEPLOY_DIR}/lib/authz.py" --model "${M}" --out "${OUT}/d2.json" render >/dev/null 2>&1
if python3 -c "import json;d=json.load(open('${OUT}/d2.json'));assert d['roles']['data-scientist']['schema_grants']['gold']['select'] is True"; then
ok "render menampilkan schema_grants"
else
bad "render tak memuat schema_grants"
fi
"${CLI}" --model "${M}" grant remove data-scientist 'gold.*' >/dev/null 2>&1
out="$(cli show role data-scientist)"
case "${out}" in *"gold.*"*) bad "grant schema tak terhapus" ;; *) ok "grant schema terhapus" ;; esac
"${CLI}" --model "${M}" user assign svc_ml data-scientist >/dev/null 2>&1
out="$(cli show user svc_ml)"
case "${out}" in *"svc_ml: data-scientist"*) ok "user assign bekerja" ;; *) bad "user assign gagal: ${out}" ;; esac
@@ -181,12 +194,43 @@ for i, (_, want) in enumerate(base_cases):
print(f" keputusan[{i}] -> {got or '(undefined)'} (harap {want})")
if got != want:
fails += 1
# Blok luas data-driven: op di LUAR op_caps (simulasi level-kolom UPDATE/MERGE)
extra = [
(tin("UpdateColumns", "iceberg", "bronze", "orders", ["id"], "u", ["data-engineer"]), "true"),
(tin("UpdateColumns", "iceberg", "gold", "orders_gold", ["id"], "u", ["data-analyst"]), "false"),
(tin("UpdateColumns", "iceberg", "other", "x", ["id"], "u", ["data-engineer"]), "false"),
]
te = build(extra)
for i, (_, want) in enumerate(extra):
got = ev(te, i)
print(f" luas[{i}] -> {got or '(undefined)'} (harap {want})")
if got != want:
fails += 1
tr = build(ren_cases, {"authz": {"catalogs": ["lakehouse"], "write_schemas": ["bronze", "silver", "gold"]}})
for i, (_, want) in enumerate(ren_cases):
got = ev(tr, i)
print(f" rename[{i}] -> {got or '(undefined)'} (harap {want})")
if got != want:
fails += 1
# Grant tingkat-schema: data-analyst dapat 'gold.*' (select)
roles = json.loads((opa / "data.json").read_text())["roles"]
roles["data-analyst"]["schema_grants"] = {"gold": {"select": True, "columns": "*"}}
sch_cases = [
(tin("SELECTFROMCOLUMNS", "iceberg", "gold", "orders_gold", ["id"], "u", ["data-analyst"]), "true"),
(tin("SELECTFROMCOLUMNS", "iceberg", "gold", "brand_new_table", ["id"], "u", ["data-analyst"]), "true"),
(tin("SELECTFROMCOLUMNS", "iceberg", "bronze", "orders", ["id"], "u", ["data-analyst"]), "false"),
(tin("SELECTFROMCOLUMNS", "iceberg", "silver", "orders_silver", ["order_date"], "u", ["data-analyst"]), "false"),
(tin("FILTERTABLES", "iceberg", "gold", "whatever", [], "u", ["data-analyst"]), "true"),
]
ts = build(sch_cases, {"roles": roles})
for i, (_, want) in enumerate(sch_cases):
got = ev(ts, i)
print(f" schema[{i}] -> {got or '(undefined)'} (harap {want})")
if got != want:
fails += 1
sys.exit(1 if fails else 0)
PY
then ok "policy OPA: perilaku dasar + ganti catalog lewat data (via docker)"