feat sicabe-authz

This commit is contained in:
2026-10-13 14:44:55 +07:00
parent 082de8e3b2
commit f534e8da54
6 changed files with 1030 additions and 17 deletions
+22 -6
View File
@@ -10,6 +10,9 @@
#
# Grup user berasal dari LDAP group provider Trino (OpenLDAP, cn = data-*).
# Izin didefinisikan sebagai data di data.json → data.roles.<grup>.tables.<schema_table>.
# Nama catalog/schema TIDAK di-hardcode di policy: dibaca dari data.authz.catalogs /
# data.authz.write_schemas (hasil render config/opa/authz.yml) → rename catalog/schema
# cukup mengubah data, bukan Rego. Lihat scripts/sicabe-authz.
# grant = { select: bool, write: bool, ddl: bool, columns: "*" | [..] }
# - data-admin : superuser (semua operasi)
# - select : SELECT/SHOW COLUMNS/DESCRIBE
@@ -30,6 +33,19 @@ op := upper(replace(replace(trim_space(input.action.operation), " ", ""), "_", "
identity_groups := input.context.identity.groups
identity_user := input.context.identity.user
# ── Nama catalog/schema dari DATA (authz.yml), JANGAN di-hardcode di sini ────
# `default` → aman (deny-by-default) bila data.authz belum ada. Rujuk path
# SPESIFIK (data.authz.*) — JANGAN meneruskan `data` utuh ke builtin, sebab itu
# membuat compiler menganggapnya bergantung pada `allow` (rego_recursion_error).
default data_catalogs := []
default write_schemas := []
data_catalogs := data.authz.catalogs
write_schemas := data.authz.write_schemas
# Catalog yang boleh di-listing = catalog terdaftar + 'system' (bawaan Trino).
allowed_catalogs contains c if { some c in data_catalogs }
allowed_catalogs contains "system"
# Role efektif = grup (dari LDAP) ∪ role user (data.users) — untuk service account
# yang tidak terdaftar di LDAP (mis. svc_dbt, svc_om dari password file Basic).
effective_roles contains r if {
@@ -105,12 +121,12 @@ allow if {
allow if {
op in {"ACCESSCATALOG", "FILTERCATALOGS"}
res := input.action.resource
res.catalog.name in {"iceberg", "system"}
res.catalog.name in allowed_catalogs
}
allow if {
op == "FILTERSCHEMAS"
res := input.action.resource
res.schema.catalogName in {"iceberg", "system"}
res.schema.catalogName in allowed_catalogs
}
allow if {
op == "FILTERTABLES"
@@ -163,7 +179,7 @@ cols_all_ok(columns, cols) if {
allow if {
op == "SELECTFROMCOLUMNS"
res := input.action.resource
res.table.catalogName == "iceberg"
res.table.catalogName in data_catalogs
tid := table_id(res.table.schemaName, res.table.tableName)
cols := res.table.columns
count(cols) > 0
@@ -180,7 +196,7 @@ allow if {
allow if {
op == "SELECTFROMCOLUMNS"
res := input.action.resource
res.table.catalogName == "iceberg"
res.table.catalogName in data_catalogs
tid := table_id(res.table.schemaName, res.table.tableName)
count(res.table.columns) == 0
some r in effective_roles
@@ -234,7 +250,7 @@ any_cap(grant) if {
allow if {
op == "FILTERTABLES"
res := input.action.resource
res.table.catalogName == "iceberg"
res.table.catalogName in data_catalogs
tid := table_id(res.table.schemaName, res.table.tableName)
some r in effective_roles
grant := data.roles[r].tables[tid]
@@ -264,7 +280,7 @@ allow if {
# eksplisit. Layer lain (silver/gold) TIDAK terpengaruh — tetap least-privilege.
allow if {
res := input.action.resource
res.table.schemaName in {"bronze", "silver", "gold"}
res.table.schemaName in write_schemas
some r in effective_roles
r == "data-engineer"
}