From 6edc3ba8816382dd487a51ff1edf5b81b2da9aee Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Mon, 4 Aug 2025 19:10:26 +0200 Subject: [PATCH 1/8] test: Improve the performance of the OPA rego rules --- .../trino_rules/requested_permissions.rego | 218 +++++----- .../requested_permissions_test.rego | 399 +++++++----------- .../opa-authorization/trino_rules/util.rego | 6 + .../trino_rules/util_test.rego | 1 + .../trino_rules/verification.rego | 84 ++-- 5 files changed, 326 insertions(+), 382 deletions(-) diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions.rego b/tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions.rego index 4a86af24..4c6e89fa 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions.rego @@ -8,12 +8,8 @@ package trino # for the file-based access control # (https://trino.io/docs/current/security/file-system-access-control.html). -action := input.action - -operation := action.operation - -requested_permissions := permissions if { - operation == "AccessCatalog" +requested_permissions(action) := permissions if { + action.operation == "AccessCatalog" permissions := {{ "resource": "catalog", "catalogName": action.resource.catalog.name, @@ -21,8 +17,8 @@ requested_permissions := permissions if { }} } -requested_permissions := permissions if { - operation in { +requested_permissions(action) := permissions if { + action.operation in { "CreateSchema", "DropSchema", "ShowCreateSchema", @@ -42,8 +38,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation in { +requested_permissions(action) := permissions if { + action.operation in { "AddColumn", "AlterColumn", "CreateMaterializedView", @@ -78,8 +74,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation in { +requested_permissions(action) := permissions if { + action.operation in { "RefreshMaterializedView", "UpdateTableColumns", } @@ -99,8 +95,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation in { +requested_permissions(action) := permissions if { + action.operation in { "DeleteFromTable", "TruncateTable", } @@ -120,23 +116,23 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation == "ExecuteQuery" +requested_permissions(action) := permissions if { + action.operation == "ExecuteQuery" permissions := {{ "resource": "query", "allow": {"execute"}, }} } -requested_permissions := permissions if { - operation == "ExecuteTableProcedure" +requested_permissions(action) := permissions if { + action.operation == "ExecuteTableProcedure" # Executing table procedures is always allowed permissions := set() } -requested_permissions := permissions if { - operation == "FilterColumns" +requested_permissions(action) := permissions if { + action.operation == "FilterColumns" permissions := { { "resource": "table", @@ -163,8 +159,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation == "KillQueryOwnedBy" +requested_permissions(action) := permissions if { + action.operation == "KillQueryOwnedBy" permissions := {{ "resource": "query_owned_by", "user": action.resource.user.user, @@ -173,8 +169,8 @@ requested_permissions := permissions if { }} } -requested_permissions := permissions if { - operation in { +requested_permissions(action) := permissions if { + action.operation in { "FilterViewQueryOwnedBy", "ViewQueryOwnedBy", } @@ -186,8 +182,8 @@ requested_permissions := permissions if { }} } -requested_permissions := permissions if { - operation == "FilterTables" +requested_permissions(action) := permissions if { + action.operation == "FilterTables" permissions := { { "resource": "catalog", @@ -211,8 +207,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation in { +requested_permissions(action) := permissions if { + action.operation in { "CreateFunction", "DropFunction", } @@ -232,8 +228,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation in { +requested_permissions(action) := permissions if { + action.operation in { "ExecuteFunction", "FilterFunctions", } @@ -253,8 +249,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation == "ExecuteProcedure" +requested_permissions(action) := permissions if { + action.operation == "ExecuteProcedure" permissions := { { "resource": "catalog", @@ -271,8 +267,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation == "CreateViewWithExecuteFunction" +requested_permissions(action) := permissions if { + action.operation == "CreateViewWithExecuteFunction" permissions := { { "resource": "catalog", @@ -289,8 +285,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation == "ImpersonateUser" +requested_permissions(action) := permissions if { + action.operation == "ImpersonateUser" permissions := {{ "resource": "impersonation", "user": action.resource.user.user, @@ -298,8 +294,8 @@ requested_permissions := permissions if { }} } -requested_permissions := permissions if { - operation == "InsertIntoTable" +requested_permissions(action) := permissions if { + action.operation == "InsertIntoTable" permissions := { { "resource": "catalog", @@ -316,16 +312,16 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation == "ReadSystemInformation" +requested_permissions(action) := permissions if { + action.operation == "ReadSystemInformation" permissions := {{ "resource": "system_information", "allow": {"read"}, }} } -requested_permissions := permissions if { - operation == "RenameSchema" +requested_permissions(action) := permissions if { + action.operation == "RenameSchema" permissions := { { "resource": "catalog", @@ -352,8 +348,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation in { +requested_permissions(action) := permissions if { + action.operation in { "RenameMaterializedView", "RenameTable", "RenameView", @@ -386,8 +382,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation == "SelectFromColumns" +requested_permissions(action) := permissions if { + action.operation == "SelectFromColumns" column_permissions := { { "resource": "column", @@ -415,8 +411,8 @@ requested_permissions := permissions if { } | column_permissions } -requested_permissions := permissions if { - operation == "SetSchemaAuthorization" +requested_permissions(action) := permissions if { + action.operation == "SetSchemaAuthorization" permissions := { { "resource": "catalog", @@ -438,8 +434,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation in { +requested_permissions(action) := permissions if { + action.operation in { "SetTableAuthorization", "SetViewAuthorization", } @@ -465,8 +461,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation == "ShowColumns" +requested_permissions(action) := permissions if { + action.operation == "ShowColumns" permissions := { { "resource": "catalog", @@ -490,8 +486,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation in { +requested_permissions(action) := permissions if { + action.operation in { "FilterCatalogs", "ShowSchemas", } @@ -508,8 +504,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation in { +requested_permissions(action) := permissions if { + action.operation in { "FilterSchemas", "ShowFunctions", "ShowTables", @@ -528,8 +524,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation == "SetCatalogSessionProperty" +requested_permissions(action) := permissions if { + action.operation == "SetCatalogSessionProperty" permissions := { { "resource": "catalog", @@ -545,8 +541,8 @@ requested_permissions := permissions if { } } -requested_permissions := permissions if { - operation == "SetSystemSessionProperty" +requested_permissions(action) := permissions if { + action.operation == "SetSystemSessionProperty" permissions := {{ "resource": "system_session_properties", "propertyName": action.resource.systemSessionProperty.name, @@ -554,91 +550,91 @@ requested_permissions := permissions if { }} } -requested_permissions := permissions if { - operation == "WriteSystemInformation" +requested_permissions(action) := permissions if { + action.operation == "WriteSystemInformation" permissions := {{ "resource": "system_information", "allow": {"write"}, }} } -requested_authorization_permissions contains permission if { - some permission in requested_permissions +requested_authorization_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "authorization" -} +] -requested_catalog_permissions contains permission if { - some permission in requested_permissions +requested_catalog_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "catalog" -} +] -requested_catalog_session_properties_permissions contains permission if { - some permission in requested_permissions +requested_catalog_session_properties_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "catalog_session_properties" -} +] -requested_catalog_visibility_permissions contains permission if { - some permission in requested_permissions +requested_catalog_visibility_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "catalog_visibility" -} +] -requested_column_permissions contains permission if { - some permission in requested_permissions +requested_column_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "column" -} +] -requested_function_permissions contains permission if { - some permission in requested_permissions +requested_function_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "function" -} +] -requested_impersonation_permissions contains permission if { - some permission in requested_permissions +requested_impersonation_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "impersonation" -} +] -requested_procedure_permissions contains permission if { - some permission in requested_permissions +requested_procedure_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "procedure" -} +] -requested_query_permissions contains permission if { - some permission in requested_permissions +requested_query_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "query" -} +] -requested_query_owned_by_permissions contains permission if { - some permission in requested_permissions +requested_query_owned_by_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "query_owned_by" -} +] -requested_schema_permissions contains permission if { - some permission in requested_permissions +requested_schema_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "schema" -} +] -requested_schema_visibility_permissions contains permission if { - some permission in requested_permissions +requested_schema_visibility_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "schema_visibility" -} +] -requested_table_permissions contains permission if { - some permission in requested_permissions +requested_table_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "table" -} +] -requested_system_information_permissions contains permission if { - some permission in requested_permissions +requested_system_information_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "system_information" -} +] -requested_system_session_properties_permissions contains permission if { - some permission in requested_permissions +requested_system_session_properties_permissions(action) := [permission | + some permission in requested_permissions(action) permission.resource == "system_session_properties" -} +] -requested_column_mask := request if { - operation == "GetColumnMask" +requested_column_mask(action) := request if { + action.operation == "GetColumnMask" request := { "catalogName": action.resource.column.catalogName, "schemaName": action.resource.column.schemaName, @@ -647,8 +643,8 @@ requested_column_mask := request if { } } -requested_row_filters := request if { - operation == "GetRowFilters" +requested_row_filters(action) := request if { + action.operation == "GetRowFilters" request := { "catalogName": action.resource.table.catalogName, "schemaName": action.resource.table.schemaName, diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions_test.rego b/tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions_test.rego index 0d7214ad..4dd2c330 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions_test.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions_test.rego @@ -279,61 +279,44 @@ permission_valid(permission) if { ) } -testcontext := { - "identity": { - "groups": ["testgroup1", "testgroup2"], - "user": "testuser", - }, - "softwareStack": {"trinoVersion": "455"}, -} - test_access_filter_catalog if { operations := { "AccessCatalog", "FilterCatalogs", } every operation in operations { - permissions := trino.requested_permissions with input as { - "action": { - "operation": operation, - "resource": {"catalog": {"name": "testcatalog"}}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": operation, + "resource": {"catalog": {"name": "testcatalog"}}, + }) permissions_valid(permissions) } } test_create_schema if { - permissions := trino.requested_permissions with input as { - "action": { - "operation": "CreateSchema", - "resource": {"schema": { - "catalogName": "testcatalog", - "schemaName": "testschema", - "properties": {}, - }}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": "CreateSchema", + "resource": {"schema": { + "catalogName": "testcatalog", + "schemaName": "testschema", + "properties": {}, + }}, + }) permissions_valid(permissions) } test_filter_columns if { - permissions := trino.requested_permissions with input as { - "action": { - "operation": "FilterColumns", - "resource": {"table": { - "catalogName": "testcatalog", - "schemaName": "testschema", - "tableName": "testtable", - "columnName": "testcolumn", - }}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": "FilterColumns", + "resource": {"table": { + "catalogName": "testcatalog", + "schemaName": "testschema", + "tableName": "testtable", + "columnName": "testcolumn", + }}, + }) permissions_valid(permissions) } @@ -348,17 +331,14 @@ test_function_resource_actions if { "FilterFunctions", } every operation in operations { - permissions := trino.requested_permissions with input as { - "action": { - "operation": operation, - "resource": {"function": { - "catalogName": "testcatalog", - "schemaName": "testschema", - "functionName": "testfunction", - }}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": operation, + "resource": {"function": { + "catalogName": "testcatalog", + "schemaName": "testschema", + "functionName": "testfunction", + }}, + }) permissions_valid(permissions) } @@ -371,30 +351,24 @@ test_no_resource_action if { "WriteSystemInformation", } every operation in operations { - permissions := trino.requested_permissions with input as { - "action": {"operation": operation}, - "context": testcontext, - } + permissions := trino.requested_permissions({"operation": operation}) permissions_valid(permissions) } } test_execute_table_procedure if { - permissions := trino.requested_permissions with input as { - "action": { - "operation": "ExecuteTableProcedure", - "resource": { - "table": { - "catalogName": "testcatalog", - "schemaName": "testschema", - "tableName": "testtable", - }, - "function": {"functionName": "testprocedure"}, + permissions := trino.requested_permissions({ + "operation": "ExecuteTableProcedure", + "resource": { + "table": { + "catalogName": "testcatalog", + "schemaName": "testschema", + "tableName": "testtable", }, + "function": {"functionName": "testprocedure"}, }, - "context": testcontext, - } + }) permissions_valid(permissions) } @@ -406,31 +380,25 @@ test_column_operations_on_table_like_objects if { "UpdateTableColumns", } every operation in operations { - permissions := trino.requested_permissions with input as { - "action": { - "operation": operation, - "resource": {"table": { - "catalogName": "testcatalog", - "schemaName": "testschema", - "tableName": "testtable", - "columns": ["testcolumn1", "testcolumn2"], - }}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": operation, + "resource": {"table": { + "catalogName": "testcatalog", + "schemaName": "testschema", + "tableName": "testtable", + "columns": ["testcolumn1", "testcolumn2"], + }}, + }) permissions_valid(permissions) } } test_show_schemas if { - permissions := trino.requested_permissions with input as { - "action": { - "operation": "ShowSchemas", - "resource": {"catalog": {"name": "testcatalog"}}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": "ShowSchemas", + "resource": {"catalog": {"name": "testcatalog"}}, + }) permissions_valid(permissions) } @@ -457,17 +425,14 @@ test_table_resource_actions if { "TruncateTable", } every operation in operations { - permissions := trino.requested_permissions with input as { - "action": { - "operation": operation, - "resource": {"table": { - "catalogName": "testcatalog", - "schemaName": "testschema", - "tableName": "testtable", - }}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": operation, + "resource": {"table": { + "catalogName": "testcatalog", + "schemaName": "testschema", + "tableName": "testtable", + }}, + }) permissions_valid(permissions) } @@ -481,22 +446,19 @@ test_table_with_properties_actions if { "SetTableProperties", } every operation in operations { - permissions := trino.requested_permissions with input as { - "action": { - "operation": operation, - "resource": {"table": { - "catalogName": "testcatalog", - "schemaName": "testschema", - "tableName": "testtable", - "properties": { - "string_item": "string_value", - "empty_item": null, - "boxed_number_item": 32, - }, - }}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": operation, + "resource": {"table": { + "catalogName": "testcatalog", + "schemaName": "testschema", + "tableName": "testtable", + "properties": { + "string_item": "string_value", + "empty_item": null, + "boxed_number_item": 32, + }, + }}, + }) permissions_valid(permissions) } @@ -509,16 +471,13 @@ test_identity_resource_actions if { "ViewQueryOwnedBy", } every operation in operations { - permissions := trino.requested_permissions with input as { - "action": { - "operation": operation, - "resource": {"user": { - "user": "testuser", - "groups": ["testgroup1", "testgroup2"], - }}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": operation, + "resource": {"user": { + "user": "testuser", + "groups": ["testgroup1", "testgroup2"], + }}, + }) permissions_valid(permissions) } @@ -533,16 +492,13 @@ test_schema_resource_actions if { "ShowTables", } every operation in operations { - permissions := trino.requested_permissions with input as { - "action": { - "operation": operation, - "resource": {"schema": { - "catalogName": "testcatalog", - "schemaName": "testschema", - }}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": operation, + "resource": {"schema": { + "catalogName": "testcatalog", + "schemaName": "testschema", + }}, + }) permissions_valid(permissions) } @@ -555,88 +511,73 @@ test_rename_table_like_object if { "RenameView", } every operation in operations { - permissions := trino.requested_permissions with input as { - "action": { - "operation": operation, - "resource": {"table": { - "catalogName": "testcatalog", - "schemaName": "testschema", - "tableName": "testtable", - }}, - "targetResource": {"table": { - "catalogName": "testcatalog", - "schemaName": "testschema", - "tableName": "newtesttable", - }}, - }, - "context": testcontext, - } - - permissions_valid(permissions) - } -} - -test_rename_schema if { - permissions := trino.requested_permissions with input as { - "action": { - "operation": "RenameSchema", - "resource": {"schema": { + permissions := trino.requested_permissions({ + "operation": operation, + "resource": {"table": { "catalogName": "testcatalog", "schemaName": "testschema", + "tableName": "testtable", }}, - "targetResource": {"schema": { + "targetResource": {"table": { "catalogName": "testcatalog", - "schemaName": "newtestschema", + "schemaName": "testschema", + "tableName": "newtesttable", }}, - }, - "context": testcontext, + }) + + permissions_valid(permissions) } +} + +test_rename_schema if { + permissions := trino.requested_permissions({ + "operation": "RenameSchema", + "resource": {"schema": { + "catalogName": "testcatalog", + "schemaName": "testschema", + }}, + "targetResource": {"schema": { + "catalogName": "testcatalog", + "schemaName": "newtestschema", + }}, + }) permissions_valid(permissions) } test_set_catalog_session_properties if { - permissions := trino.requested_permissions with input as { - "action": { - "operation": "SetCatalogSessionProperty", - "resource": {"catalogSessionProperty": { - "catalogName": "testcatalog", - "propertyName": "testproperty", - }}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": "SetCatalogSessionProperty", + "resource": {"catalogSessionProperty": { + "catalogName": "testcatalog", + "propertyName": "testproperty", + }}, + }) permissions_valid(permissions) } test_set_system_session_properties if { - permissions := trino.requested_permissions with input as { - "action": { - "operation": "SetSystemSessionProperty", - "resource": {"systemSessionProperty": {"name": "testproperty"}}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": "SetSystemSessionProperty", + "resource": {"systemSessionProperty": {"name": "testproperty"}}, + }) permissions_valid(permissions) } test_set_schema_authorization if { - permissions := trino.requested_permissions with input as { - "action": { - "operation": "SetSchemaAuthorization", - "resource": {"schema": { - "catalogName": "testcatalog", - "schemaName": "testschema", - }}, - "grantee": { - "name": "testuser", - "type": "testusertype", - }, + permissions := trino.requested_permissions({ + "operation": "SetSchemaAuthorization", + "resource": {"schema": { + "catalogName": "testcatalog", + "schemaName": "testschema", + }}, + "grantee": { + "name": "testuser", + "type": "testusertype", }, - "context": testcontext, - } + }) permissions_valid(permissions) } @@ -647,51 +588,42 @@ test_set_authorization_on_table_like_object if { "SetViewAuthorization", } every operation in operations { - permissions := trino.requested_permissions with input as { - "action": { - "operation": operation, - "resource": {"table": { - "catalogName": "testcatalog", - "schemaName": "testschema", - "tableName": "testtable", - }}, - "grantee": { - "name": "testuser", - "type": "testusertype", - }, + permissions := trino.requested_permissions({ + "operation": operation, + "resource": {"table": { + "catalogName": "testcatalog", + "schemaName": "testschema", + "tableName": "testtable", + }}, + "grantee": { + "name": "testuser", + "type": "testusertype", }, - "context": testcontext, - } + }) permissions_valid(permissions) } } test_impersonate_user if { - permissions := trino.requested_permissions with input as { - "action": { - "operation": "ImpersonateUser", - "resource": {"user": {"user": "testuser"}}, - }, - "context": testcontext, - } + permissions := trino.requested_permissions({ + "operation": "ImpersonateUser", + "resource": {"user": {"user": "testuser"}}, + }) permissions_valid(permissions) } test_get_column_mask if { - request := trino.requested_column_mask with input as { - "action": { - "operation": "GetColumnMask", - "resource": {"column": { - "catalogName": "testcatalog", - "schemaName": "testschema", - "tableName": "testtable", - "columnName": "testcolumn", - }}, - }, - "context": testcontext, - } + request := trino.requested_column_mask({ + "operation": "GetColumnMask", + "resource": {"column": { + "catalogName": "testcatalog", + "schemaName": "testschema", + "tableName": "testtable", + "columnName": "testcolumn", + }}, + }) request.catalogName == "testcatalog" request.schemaName == "testschema" @@ -700,17 +632,14 @@ test_get_column_mask if { } test_get_row_filters if { - request := trino.requested_row_filters with input as { - "action": { - "operation": "GetRowFilters", - "resource": {"table": { - "catalogName": "testcatalog", - "schemaName": "testschema", - "tableName": "testtable", - }}, - }, - "context": testcontext, - } + request := trino.requested_row_filters({ + "operation": "GetRowFilters", + "resource": {"table": { + "catalogName": "testcatalog", + "schemaName": "testschema", + "tableName": "testtable", + }}, + }) request.catalogName == "testcatalog" request.schemaName == "testschema" diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/util.rego b/tests/templates/kuttl/opa-authorization/trino_rules/util.rego index 9b0978f4..0182c03e 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/util.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/util.rego @@ -12,6 +12,12 @@ package util # Returns: # result (boolean) match_entire(pattern, value) if { + pattern == `.*` +} + +match_entire(pattern, value) if { + pattern != `.*` + # Add the anchors ^ and $ pattern_with_anchors := concat("", ["^", pattern, "$"]) diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/util_test.rego b/tests/templates/kuttl/opa-authorization/trino_rules/util_test.rego index 87a4f695..dd2d1e37 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/util_test.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/util_test.rego @@ -3,6 +3,7 @@ package util_test import data.util test_match_entire if { + util.match_entire(`.*`, "a") util.match_entire(`a`, "a") util.match_entire(`^a`, "a") util.match_entire(`a$`, "a") diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/verification.rego b/tests/templates/kuttl/opa-authorization/trino_rules/verification.rego index a5d9568b..9e001fc1 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/verification.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/verification.rego @@ -62,34 +62,36 @@ package trino # entrypoint: true default allow := false -allow if { +allow := allowWith(input.action) + +allowWith(action) if { # Fail if the requested permissions for the given operation are not # implemented yet # # The following operations are intentionally not supported: # - CreateCatalog # - DropCatalog - requested_permissions + requested_permissions(action) - every requested_permission in requested_authorization_permissions { + every requested_permission in requested_authorization_permissions(action) { permission := authorization_permission(requested_permission.granteeName) requested_permission.allow == permission } - every requested_permission in requested_catalog_permissions { + every requested_permission in requested_catalog_permissions(action) { access := catalog_access(requested_permission.catalogName) requested_permission.allow in access } - every requested_permission in requested_catalog_session_properties_permissions { + every requested_permission in requested_catalog_session_properties_permissions(action) { access := catalog_session_properties_access( requested_permission.catalogName, requested_permission.propertyName, ) requested_permission.allow == access } - every requested_permission in requested_catalog_visibility_permissions { + every requested_permission in requested_catalog_visibility_permissions(action) { catalog_visibility(requested_permission.catalogName) } - every requested_permission in requested_column_permissions { + every requested_permission in requested_column_permissions(action) { access := column_access( requested_permission.catalogName, requested_permission.schemaName, @@ -98,7 +100,7 @@ allow if { ) requested_permission.allow == access } - every requested_permission in requested_function_permissions { + every requested_permission in requested_function_permissions(action) { privileges := function_privileges( requested_permission.catalogName, requested_permission.schemaName, @@ -106,11 +108,11 @@ allow if { ) object.subset(privileges, requested_permission.privileges) } - every requested_permission in requested_impersonation_permissions { + every requested_permission in requested_impersonation_permissions(action) { access := impersonation_access(requested_permission.user) requested_permission.allow == access } - every requested_permission in requested_procedure_permissions { + every requested_permission in requested_procedure_permissions(action) { privileges := procedure_privileges( requested_permission.catalogName, requested_permission.schemaName, @@ -118,28 +120,28 @@ allow if { ) object.subset(privileges, requested_permission.privileges) } - every requested_permission in requested_query_permissions { + every requested_permission in requested_query_permissions(action) { object.subset(query_access, requested_permission.allow) } - every requested_permission in requested_query_owned_by_permissions { + every requested_permission in requested_query_owned_by_permissions(action) { object.subset( query_owned_by_access(requested_permission.user), requested_permission.allow, ) } - every requested_permission in requested_schema_permissions { + every requested_permission in requested_schema_permissions(action) { schema_owner( requested_permission.catalogName, requested_permission.schemaName, ) == requested_permission.owner } - every requested_permission in requested_schema_visibility_permissions { + every requested_permission in requested_schema_visibility_permissions(action) { schema_visibility( requested_permission.catalogName, requested_permission.schemaName, ) } - every requested_permission in requested_table_permissions { + every requested_permission in requested_table_permissions(action) { privileges := table_privileges( requested_permission.catalogName, requested_permission.schemaName, @@ -158,13 +160,13 @@ allow if { object.subset(privileges, all_of_requested) privileges & any_of_requested != set() } - every requested_permission in requested_system_information_permissions { + every requested_permission in requested_system_information_permissions(action) { object.subset( system_information_access, requested_permission.allow, ) } - every requested_permission in requested_system_session_properties_permissions { + every requested_permission in requested_system_session_properties_permissions(action) { access := system_session_properties_access(requested_permission.propertyName) requested_permission.allow == access } @@ -209,8 +211,9 @@ batch contains index if { some index, resource in input.action.filterResources - # regal ignore:with-outside-test-context - allow with input.action.resource as resource + action := object.union(object.remove(input.action, {"filterResources"}), {"resource": resource}) + + allowWith(action) } batch contains index if { @@ -219,13 +222,14 @@ batch contains index if { table := input.action.filterResources[0].table some index, column_name in table.columns - # regal ignore:with-outside-test-context - allow with input.action.resource as {"table": { + action := object.union(object.remove(input.action, {"filterResources"}), {"resource": {"table": { "catalogName": table.catalogName, "schemaName": table.schemaName, "tableName": table.tableName, "columnName": column_name, - }} + }}}) + + allowWith(action) } # METADATA @@ -264,11 +268,13 @@ batch contains index if { # is an SQL expression, e.g. "'XXX-XX-' + substring(credit_card, -4)". # entrypoint: true columnMask := column_mask if { + request := requested_column_mask(input.action) + column := column_constraints( - requested_column_mask.catalogName, - requested_column_mask.schemaName, - requested_column_mask.tableName, - requested_column_mask.columnName, + request.catalogName, + request.schemaName, + request.tableName, + request.columnName, ) is_string(column.mask) @@ -281,11 +287,13 @@ columnMask := column_mask if { } columnMask := column_mask if { + request := requested_column_mask(input.action) + column := column_constraints( - requested_column_mask.catalogName, - requested_column_mask.schemaName, - requested_column_mask.tableName, - requested_column_mask.columnName, + request.catalogName, + request.schemaName, + request.tableName, + request.columnName, ) is_string(column.mask) @@ -329,10 +337,12 @@ columnMask := column_mask if { # an SQL condition, e.g. "user = current_user". # entrypoint: true rowFilters contains row_filter if { + request := requested_row_filters(input.action) + rule := first_matching_table_rule( - requested_row_filters.catalogName, - requested_row_filters.schemaName, - requested_row_filters.tableName, + request.catalogName, + request.schemaName, + request.tableName, ) is_string(rule.filter) @@ -345,10 +355,12 @@ rowFilters contains row_filter if { } rowFilters contains row_filter if { + request := requested_row_filters(input.action) + rule := first_matching_table_rule( - requested_row_filters.catalogName, - requested_row_filters.schemaName, - requested_row_filters.tableName, + request.catalogName, + request.schemaName, + request.tableName, ) is_string(rule.filter) From 418ff505d61b6e356f06410e22779b730be134b2 Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Tue, 5 Aug 2025 09:33:00 +0200 Subject: [PATCH 2/8] test: Use common directory structure for OPA rules --- .../{ => trino}/actual_permissions.rego | 54 +++++++++---------- .../{ => trino}/actual_permissions_test.rego | 2 +- .../trino_rules/{ => trino}/policies.rego | 2 - .../{ => trino}/policies_test.rego | 2 +- .../{ => trino}/requested_permissions.rego | 0 .../requested_permissions_test.rego | 2 +- .../trino_rules/{ => trino}/util.rego | 5 +- .../trino_rules/trino/util_test.rego | 14 +++++ .../trino_rules/{ => trino}/verification.rego | 0 .../{ => trino}/verification_test.rego | 2 +- .../trino_rules/util_test.rego | 14 ----- 11 files changed, 46 insertions(+), 51 deletions(-) rename tests/templates/kuttl/opa-authorization/trino_rules/{ => trino}/actual_permissions.rego (89%) rename tests/templates/kuttl/opa-authorization/trino_rules/{ => trino}/actual_permissions_test.rego (99%) rename tests/templates/kuttl/opa-authorization/trino_rules/{ => trino}/policies.rego (99%) rename tests/templates/kuttl/opa-authorization/trino_rules/{ => trino}/policies_test.rego (99%) rename tests/templates/kuttl/opa-authorization/trino_rules/{ => trino}/requested_permissions.rego (100%) rename tests/templates/kuttl/opa-authorization/trino_rules/{ => trino}/requested_permissions_test.rego (99%) rename tests/templates/kuttl/opa-authorization/trino_rules/{ => trino}/util.rego (83%) create mode 100644 tests/templates/kuttl/opa-authorization/trino_rules/trino/util_test.rego rename tests/templates/kuttl/opa-authorization/trino_rules/{ => trino}/verification.rego (100%) rename tests/templates/kuttl/opa-authorization/trino_rules/{ => trino}/verification_test.rego (99%) delete mode 100644 tests/templates/kuttl/opa-authorization/trino_rules/util_test.rego diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/actual_permissions.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego similarity index 89% rename from tests/templates/kuttl/opa-authorization/trino_rules/actual_permissions.rego rename to tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego index e2e80184..8a73886a 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/actual_permissions.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego @@ -1,7 +1,5 @@ package trino -import data.util - # This file contains functions to determine the actual permissions # defined in the Trino policies for the given user and requested # resource. @@ -41,7 +39,7 @@ default match_any_group(_) := false match_any_group(group_pattern) if { some group in groups - util.match_entire(group_pattern, group) + match_entire(group_pattern, group) } default match_user_group(_) := false @@ -50,7 +48,7 @@ match_user_group(rule) if { user_pattern := object.get(rule, "user", ".*") group_pattern := object.get(rule, "group", ".*") - util.match_entire(user_pattern, identity.user) + match_entire(user_pattern, identity.user) match_any_group(group_pattern) } @@ -60,7 +58,7 @@ match_original_user_group(rule) if { user_pattern := object.get(rule, "original_user", ".*") group_pattern := object.get(rule, "original_group", ".*") - util.match_entire(user_pattern, identity.user) + match_entire(user_pattern, identity.user) match_any_group(group_pattern) } @@ -72,7 +70,7 @@ first_matching_authorization_rule(grantee_name) := rule if { new_user_pattern := object.get(rule, "new_user", ".*") - util.match_entire(new_user_pattern, grantee_name) + match_entire(new_user_pattern, grantee_name) ] rule := object.union( {"allow": true}, @@ -92,7 +90,7 @@ first_matching_catalog_rule(catalog_name) := rule if { catalog_pattern := object.get(rule, "catalog", ".*") - util.match_entire(catalog_pattern, catalog_name) + match_entire(catalog_pattern, catalog_name) ] rule := rules[0] } @@ -119,8 +117,8 @@ first_matching_catalog_session_properties_rule( catalog_pattern := object.get(rule, "catalog", ".*") property_pattern := object.get(rule, "property", ".*") - util.match_entire(catalog_pattern, catalog_name) - util.match_entire(property_pattern, property_name) + match_entire(catalog_pattern, catalog_name) + match_entire(property_pattern, property_name) ] rule := rules[0] } @@ -150,7 +148,7 @@ catalog_visibility(catalog_name) if { catalog_pattern := object.get(rule, "catalog", ".*") - util.match_entire(catalog_pattern, catalog_name) + match_entire(catalog_pattern, catalog_name) rule.owner == true } @@ -172,7 +170,7 @@ catalog_visibility(catalog_name) if { catalog_pattern := object.get(rule, "catalog", ".*") - util.match_entire(catalog_pattern, catalog_name) + match_entire(catalog_pattern, catalog_name) count(rule.privileges) != 0 } @@ -186,7 +184,7 @@ catalog_visibility(catalog_name) if { catalog_pattern := object.get(rule, "catalog", ".*") - util.match_entire(catalog_pattern, catalog_name) + match_entire(catalog_pattern, catalog_name) rule.allow == true } @@ -205,9 +203,9 @@ first_matching_function_rule( schema_pattern := object.get(rule, "schema", ".*") function_pattern := object.get(rule, "function", ".*") - util.match_entire(catalog_pattern, catalog_name) - util.match_entire(schema_pattern, schema_name) - util.match_entire(function_pattern, function_name) + match_entire(catalog_pattern, catalog_name) + match_entire(schema_pattern, schema_name) + match_entire(function_pattern, function_name) ] rule := rules[0] } @@ -251,7 +249,7 @@ first_matching_impersonation_rule(user) := rule if { unsubstituted_new_user_pattern, ) - util.match_entire(new_user_pattern, user) + match_entire(new_user_pattern, user) ] rule := object.union( {"allow": true}, @@ -289,9 +287,9 @@ first_matching_procedure_rule( schema_pattern := object.get(rule, "schema", ".*") procedure_pattern := object.get(rule, "procedure", ".*") - util.match_entire(catalog_pattern, catalog_name) - util.match_entire(schema_pattern, schema_name) - util.match_entire(procedure_pattern, function_name) + match_entire(catalog_pattern, catalog_name) + match_entire(schema_pattern, schema_name) + match_entire(procedure_pattern, function_name) ] rule := rules[0] } @@ -331,7 +329,7 @@ first_matching_query_owned_by_rule(user) := rule if { query_owner_pattern := object.get(rule, "queryOwner", ".*") - util.match_entire(query_owner_pattern, user) + match_entire(query_owner_pattern, user) ] rule := rules[0] } @@ -358,8 +356,8 @@ first_matching_schema_rule(catalog_name, schema_name) := rule if { catalog_pattern := object.get(rule, "catalog", ".*") schema_pattern := object.get(rule, "schema", ".*") - util.match_entire(catalog_pattern, catalog_name) - util.match_entire(schema_pattern, schema_name) + match_entire(catalog_pattern, catalog_name) + match_entire(schema_pattern, schema_name) ] rule := rules[0] } @@ -397,8 +395,8 @@ schema_visibility(catalog_name, schema_name) if { catalog_pattern := object.get(rule, "catalog", ".*") schema_pattern := object.get(rule, "schema", ".*") - util.match_entire(catalog_pattern, catalog_name) - util.match_entire(schema_pattern, schema_name) + match_entire(catalog_pattern, catalog_name) + match_entire(schema_pattern, schema_name) count(rule.privileges) != 0 } @@ -432,9 +430,9 @@ first_matching_table_rule( schema_pattern := object.get(rule, "schema", ".*") table_pattern := object.get(rule, "table", ".*") - util.match_entire(catalog_pattern, catalog_name) - util.match_entire(schema_pattern, schema_name) - util.match_entire(table_pattern, table_name) + match_entire(catalog_pattern, catalog_name) + match_entire(schema_pattern, schema_name) + match_entire(table_pattern, table_name) ] rule := object.union( { @@ -545,7 +543,7 @@ first_matching_system_session_properties_rule(property_name) := rule if { property_name_pattern := object.get(rule, "property", ".*") - util.match_entire(property_name_pattern, property_name) + match_entire(property_name_pattern, property_name) ] rule := rules[0] } diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/actual_permissions_test.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions_test.rego similarity index 99% rename from tests/templates/kuttl/opa-authorization/trino_rules/actual_permissions_test.rego rename to tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions_test.rego index c7cc8122..3c48bdec 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/actual_permissions_test.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions_test.rego @@ -1,4 +1,4 @@ -package actual_permissions_test +package trino_test import data.trino diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/policies.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/policies.rego similarity index 99% rename from tests/templates/kuttl/opa-authorization/trino_rules/policies.rego rename to tests/templates/kuttl/opa-authorization/trino_rules/trino/policies.rego index a8a3d484..38c4cad3 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/policies.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/policies.rego @@ -1,7 +1,5 @@ package trino -import data.util - # The final policies are a combination of policies offered by Stackable, # policies provided externally, and default policies. # Stackable's policies form the beginnings of the rule lists, i.e. they diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/policies_test.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/policies_test.rego similarity index 99% rename from tests/templates/kuttl/opa-authorization/trino_rules/policies_test.rego rename to tests/templates/kuttl/opa-authorization/trino_rules/trino/policies_test.rego index 848ab8fc..4e2a91f6 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/policies_test.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/policies_test.rego @@ -1,4 +1,4 @@ -package policies_test +package trino_test import data.trino diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/requested_permissions.rego similarity index 100% rename from tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions.rego rename to tests/templates/kuttl/opa-authorization/trino_rules/trino/requested_permissions.rego diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions_test.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/requested_permissions_test.rego similarity index 99% rename from tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions_test.rego rename to tests/templates/kuttl/opa-authorization/trino_rules/trino/requested_permissions_test.rego index 4dd2c330..8fc900de 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions_test.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/requested_permissions_test.rego @@ -1,4 +1,4 @@ -package requested_permissions_test +package trino_test import data.trino diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/util.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/util.rego similarity index 83% rename from tests/templates/kuttl/opa-authorization/trino_rules/util.rego rename to tests/templates/kuttl/opa-authorization/trino_rules/trino/util.rego index 0182c03e..537bb2e7 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/util.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/util.rego @@ -1,6 +1,4 @@ -# METADATA -# description: Utility package which extends the built-in functions -package util +package trino # METADATA # description: | @@ -11,6 +9,7 @@ package util # # Returns: # result (boolean) +# scope: document match_entire(pattern, value) if { pattern == `.*` } diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/trino/util_test.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/util_test.rego new file mode 100644 index 00000000..c4dedb9d --- /dev/null +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/util_test.rego @@ -0,0 +1,14 @@ +package trino_test + +import data.trino + +test_match_entire if { + trino.match_entire(`.*`, "a") + trino.match_entire(`a`, "a") + trino.match_entire(`^a`, "a") + trino.match_entire(`a$`, "a") + trino.match_entire(`^a$`, "a") + not trino.match_entire(`a`, "abc") + not trino.match_entire(`b`, "abc") + not trino.match_entire(`c`, "abc") +} diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/verification.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/verification.rego similarity index 100% rename from tests/templates/kuttl/opa-authorization/trino_rules/verification.rego rename to tests/templates/kuttl/opa-authorization/trino_rules/trino/verification.rego diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/verification_test.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/verification_test.rego similarity index 99% rename from tests/templates/kuttl/opa-authorization/trino_rules/verification_test.rego rename to tests/templates/kuttl/opa-authorization/trino_rules/trino/verification_test.rego index 71f0f9d2..007c5868 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/verification_test.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/verification_test.rego @@ -1,4 +1,4 @@ -package verification_test +package trino_test import data.trino diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/util_test.rego b/tests/templates/kuttl/opa-authorization/trino_rules/util_test.rego deleted file mode 100644 index dd2d1e37..00000000 --- a/tests/templates/kuttl/opa-authorization/trino_rules/util_test.rego +++ /dev/null @@ -1,14 +0,0 @@ -package util_test - -import data.util - -test_match_entire if { - util.match_entire(`.*`, "a") - util.match_entire(`a`, "a") - util.match_entire(`^a`, "a") - util.match_entire(`a$`, "a") - util.match_entire(`^a$`, "a") - not util.match_entire(`a`, "abc") - not util.match_entire(`b`, "abc") - not util.match_entire(`c`, "abc") -} From 6f4d5a42f917ac773e7d736744c1cf6aee95bc67 Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Tue, 5 Aug 2025 09:35:23 +0200 Subject: [PATCH 3/8] test: Use pattern matching in function arguments --- .../kuttl/opa-authorization/trino_rules/trino/util.rego | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/trino/util.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/util.rego index 537bb2e7..76cee644 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/trino/util.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/util.rego @@ -10,9 +10,7 @@ package trino # Returns: # result (boolean) # scope: document -match_entire(pattern, value) if { - pattern == `.*` -} +match_entire(`.*`, value) match_entire(pattern, value) if { pattern != `.*` From ae2eb861be26f9099d6a5c9a718f7e76cfd58a3c Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Tue, 5 Aug 2025 09:36:13 +0200 Subject: [PATCH 4/8] test: Fix METADATA scope --- .../opa-authorization/trino_rules/trino/actual_permissions.rego | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego index 8a73886a..6ab29912 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego @@ -24,6 +24,7 @@ identity := input.context.identity # Example: # package trino_policies # extra_groups := data.stackable.opa.userinfo.v1.userInfoByUsername(input.context.identity.user).groups +# scope: document default extra_groups := [] extra_groups := data.trino_policies.extra_groups From cccc32bfcef27181d6d4c4e5fc040dc14e875a15 Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Tue, 5 Aug 2025 09:38:33 +0200 Subject: [PATCH 5/8] test: Defer assignments to improve performance slightly --- .../trino_rules/trino/actual_permissions.rego | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego index 6ab29912..91f8771e 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego @@ -47,9 +47,9 @@ default match_user_group(_) := false match_user_group(rule) if { user_pattern := object.get(rule, "user", ".*") - group_pattern := object.get(rule, "group", ".*") - match_entire(user_pattern, identity.user) + + group_pattern := object.get(rule, "group", ".*") match_any_group(group_pattern) } @@ -57,9 +57,9 @@ default match_original_user_group(_) := false match_original_user_group(rule) if { user_pattern := object.get(rule, "original_user", ".*") - group_pattern := object.get(rule, "original_group", ".*") - match_entire(user_pattern, identity.user) + + group_pattern := object.get(rule, "original_group", ".*") match_any_group(group_pattern) } @@ -394,9 +394,9 @@ schema_visibility(catalog_name, schema_name) if { match_user_group(rule) catalog_pattern := object.get(rule, "catalog", ".*") - schema_pattern := object.get(rule, "schema", ".*") - match_entire(catalog_pattern, catalog_name) + + schema_pattern := object.get(rule, "schema", ".*") match_entire(schema_pattern, schema_name) count(rule.privileges) != 0 From 26853f4685f930eb688f0a3901fe1ba85df956b5 Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Tue, 5 Aug 2025 10:28:33 +0200 Subject: [PATCH 6/8] test: Update Regal linter config --- .../trino_rules/.regal/config.yaml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/.regal/config.yaml b/tests/templates/kuttl/opa-authorization/trino_rules/.regal/config.yaml index e6c48524..fd2fe58d 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/.regal/config.yaml +++ b/tests/templates/kuttl/opa-authorization/trino_rules/.regal/config.yaml @@ -1,17 +1,13 @@ --- rules: + imports: + unresolved-reference: + # `data.trino_policies` is provided by the user and not included + # in the general trino rules. + except-paths: + - data.trino_policies.policies + - data.trino_policies.extra_groups style: - external-reference: - ignore: - files: - # The policy rules are used in the first_matching_rule - # functions. To avoid these external references to the policy - # rules, it would be necessary to add them as a parameter to - # all functions, and call these functions even from - # verification.rego with this parameter. Therefore, this - # linter warning is ignored because the policy rules are - # seen as the context for the actual_permissions.rego. - - actual_permissions.rego file-length: ignore: files: From 5a51c461f84c30c28d3e5b72f5ab76633c1ba280 Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Tue, 5 Aug 2025 11:45:59 +0200 Subject: [PATCH 7/8] test: Pre-compute the user/group policies --- .../trino_rules/trino/actual_permissions.rego | 137 ++++++++++-------- 1 file changed, 75 insertions(+), 62 deletions(-) diff --git a/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego b/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego index 91f8771e..9024b922 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/actual_permissions.rego @@ -36,6 +36,61 @@ groups := array.concat( [""], ) +original_user_group_authorization_policies := [rule | + some rule in policies.authorization + match_original_user_group(rule) +] + +original_user_group_impersonation_policies := [rule | + some rule in policies.impersonation + match_original_user_group(rule) +] + +user_group_catalog_policies := [rule | + some rule in policies.catalogs + match_user_group(rule) +] + +user_group_catalog_session_property_policies := [rule | + some rule in policies.catalog_session_properties + match_user_group(rule) +] + +user_group_function_policies := [rule | + some rule in policies.functions + match_user_group(rule) +] + +user_group_procedure_policies := [rule | + some rule in policies.procedures + match_user_group(rule) +] + +user_group_query_policies := [rule | + some rule in policies.queries + match_user_group(rule) +] + +user_group_schema_policies := [rule | + some rule in policies.schemas + match_user_group(rule) +] + +user_group_system_information_policies := [rule | + some rule in policies.system_information + match_user_group(rule) +] + +user_group_system_session_property_policies := [rule | + some rule in policies.system_session_properties + match_user_group(rule) +] + +user_group_table_policies := [rule | + some rule in policies.tables + match_user_group(rule) +] + default match_any_group(_) := false match_any_group(group_pattern) if { @@ -65,9 +120,7 @@ match_original_user_group(rule) if { first_matching_authorization_rule(grantee_name) := rule if { rules := [rule | - some rule in policies.authorization - - match_original_user_group(rule) + some rule in original_user_group_authorization_policies new_user_pattern := object.get(rule, "new_user", ".*") @@ -85,9 +138,7 @@ authorization_permission(grantee_name) := first_matching_authorization_rule(gran first_matching_catalog_rule(catalog_name) := rule if { rules := [rule | - some rule in policies.catalogs - - match_user_group(rule) + some rule in user_group_catalog_policies catalog_pattern := object.get(rule, "catalog", ".*") @@ -111,9 +162,7 @@ first_matching_catalog_session_properties_rule( property_name, ) := rule if { rules := [rule | - some rule in policies.catalog_session_properties - - match_user_group(rule) + some rule in user_group_catalog_session_property_policies catalog_pattern := object.get(rule, "catalog", ".*") property_pattern := object.get(rule, "property", ".*") @@ -143,9 +192,7 @@ catalog_visibility(catalog_name) if { catalog_visibility(catalog_name) if { catalog_access(catalog_name) == {"read-only"} - some rule in policies.schemas - - match_user_group(rule) + some rule in user_group_schema_policies catalog_pattern := object.get(rule, "catalog", ".*") @@ -159,16 +206,14 @@ catalog_visibility(catalog_name) if { rules := array.concat( array.concat( - policies.tables, - policies.functions, + user_group_table_policies, + user_group_function_policies, ), - policies.procedures, + user_group_procedure_policies, ) some rule in rules - match_user_group(rule) - catalog_pattern := object.get(rule, "catalog", ".*") match_entire(catalog_pattern, catalog_name) @@ -179,9 +224,7 @@ catalog_visibility(catalog_name) if { catalog_visibility(catalog_name) if { catalog_access(catalog_name) == {"read-only"} - some rule in policies.catalog_session_properties - - match_user_group(rule) + some rule in user_group_catalog_session_property_policies catalog_pattern := object.get(rule, "catalog", ".*") @@ -196,9 +239,7 @@ first_matching_function_rule( function_name, ) := rule if { rules := [rule | - some rule in policies.functions - - match_user_group(rule) + some rule in user_group_function_policies catalog_pattern := object.get(rule, "catalog", ".*") schema_pattern := object.get(rule, "schema", ".*") @@ -227,9 +268,7 @@ function_privileges( first_matching_impersonation_rule(user) := rule if { rules := [rule | - some rule in policies.impersonation - - match_original_user_group(rule) + some rule in original_user_group_impersonation_policies original_user_pattern := object.get(rule, "original_user", ".*") unsubstituted_new_user_pattern := object.get(rule, "new_user", ".*") @@ -280,9 +319,7 @@ first_matching_procedure_rule( function_name, ) := rule if { rules := [rule | - some rule in policies.procedures - - match_user_group(rule) + some rule in user_group_procedure_policies catalog_pattern := object.get(rule, "catalog", ".*") schema_pattern := object.get(rule, "schema", ".*") @@ -309,14 +346,7 @@ procedure_privileges( ).privileges } -first_matching_query_rule := rule if { - rules := [rule | - some rule in policies.queries - - match_user_group(rule) - ] - rule := rules[0] -} +first_matching_query_rule := user_group_query_policies[0] default query_access := set() @@ -324,9 +354,7 @@ query_access := {access | some access in first_matching_query_rule.allow} first_matching_query_owned_by_rule(user) := rule if { rules := [rule | - some rule in policies.queries - - match_user_group(rule) + some rule in user_group_query_policies query_owner_pattern := object.get(rule, "queryOwner", ".*") @@ -350,9 +378,7 @@ query_owned_by_access(user) := access if { first_matching_schema_rule(catalog_name, schema_name) := rule if { rules := [rule | - some rule in policies.schemas - - match_user_group(rule) + some rule in user_group_schema_policies catalog_pattern := object.get(rule, "catalog", ".*") schema_pattern := object.get(rule, "schema", ".*") @@ -383,16 +409,14 @@ schema_visibility(catalog_name, schema_name) if { rules := array.concat( array.concat( - policies.tables, - policies.functions, + user_group_table_policies, + user_group_function_policies, ), - policies.procedures, + user_group_procedure_policies, ) some rule in rules - match_user_group(rule) - catalog_pattern := object.get(rule, "catalog", ".*") match_entire(catalog_pattern, catalog_name) @@ -423,9 +447,7 @@ first_matching_table_rule( ) := rule if { schema_name != "information_schema" rules := [rule | - some rule in policies.tables - - match_user_group(rule) + some rule in user_group_table_policies catalog_pattern := object.get(rule, "catalog", ".*") schema_pattern := object.get(rule, "schema", ".*") @@ -521,14 +543,7 @@ column_access( access := column.allow } -first_matching_system_information_rule := rule if { - rules := [rule | - some rule in policies.system_information - - match_user_group(rule) - ] - rule := rules[0] -} +first_matching_system_information_rule := user_group_system_information_policies[0] default system_information_access := set() @@ -538,9 +553,7 @@ system_information_access := {access | first_matching_system_session_properties_rule(property_name) := rule if { rules := [rule | - some rule in policies.system_session_properties - - match_user_group(rule) + some rule in user_group_system_session_property_policies property_name_pattern := object.get(rule, "property", ".*") From ccb26cc7c8c4c2461e773a8f67fac10758d5aacb Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Tue, 5 Aug 2025 12:30:31 +0200 Subject: [PATCH 8/8] test: Fix paths of the Rego files --- .../templates/kuttl/opa-authorization/11-opa-rego.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/templates/kuttl/opa-authorization/11-opa-rego.yaml b/tests/templates/kuttl/opa-authorization/11-opa-rego.yaml index 23554317..6636edb3 100644 --- a/tests/templates/kuttl/opa-authorization/11-opa-rego.yaml +++ b/tests/templates/kuttl/opa-authorization/11-opa-rego.yaml @@ -6,11 +6,11 @@ commands: # Trino Rego rules provided by the Stackable Data Platform kubectl create configmap trino-opa-rules \ --namespace=$NAMESPACE \ - --from-file=trino_rules/actual_permissions.rego \ - --from-file=trino_rules/policies.rego \ - --from-file=trino_rules/requested_permissions.rego \ - --from-file=trino_rules/util.rego \ - --from-file=trino_rules/verification.rego + --from-file=trino_rules/trino/actual_permissions.rego \ + --from-file=trino_rules/trino/policies.rego \ + --from-file=trino_rules/trino/requested_permissions.rego \ + --from-file=trino_rules/trino/util.rego \ + --from-file=trino_rules/trino/verification.rego kubectl label configmaps trino-opa-rules \ opa.stackable.tech/bundle=true \ --namespace=$NAMESPACE