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 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: 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 76% 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..9024b922 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. @@ -26,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 @@ -37,20 +36,75 @@ 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 { some group in groups - util.match_entire(group_pattern, group) + match_entire(group_pattern, group) } 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) - util.match_entire(user_pattern, identity.user) + group_pattern := object.get(rule, "group", ".*") match_any_group(group_pattern) } @@ -58,21 +112,19 @@ 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) - util.match_entire(user_pattern, identity.user) + group_pattern := object.get(rule, "original_group", ".*") match_any_group(group_pattern) } 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", ".*") - util.match_entire(new_user_pattern, grantee_name) + match_entire(new_user_pattern, grantee_name) ] rule := object.union( {"allow": true}, @@ -86,13 +138,11 @@ 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", ".*") - util.match_entire(catalog_pattern, catalog_name) + match_entire(catalog_pattern, catalog_name) ] rule := rules[0] } @@ -112,15 +162,13 @@ 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", ".*") - 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] } @@ -144,13 +192,11 @@ 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", ".*") - util.match_entire(catalog_pattern, catalog_name) + match_entire(catalog_pattern, catalog_name) rule.owner == true } @@ -160,19 +206,17 @@ 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", ".*") - util.match_entire(catalog_pattern, catalog_name) + match_entire(catalog_pattern, catalog_name) count(rule.privileges) != 0 } @@ -180,13 +224,11 @@ 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", ".*") - util.match_entire(catalog_pattern, catalog_name) + match_entire(catalog_pattern, catalog_name) rule.allow == true } @@ -197,17 +239,15 @@ 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", ".*") 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] } @@ -228,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", ".*") @@ -251,7 +289,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}, @@ -281,17 +319,15 @@ 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", ".*") 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] } @@ -310,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() @@ -325,13 +354,11 @@ 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", ".*") - util.match_entire(query_owner_pattern, user) + match_entire(query_owner_pattern, user) ] rule := rules[0] } @@ -351,15 +378,13 @@ 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", ".*") - 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] } @@ -384,21 +409,19 @@ 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", ".*") - schema_pattern := object.get(rule, "schema", ".*") + match_entire(catalog_pattern, catalog_name) - util.match_entire(catalog_pattern, catalog_name) - util.match_entire(schema_pattern, schema_name) + schema_pattern := object.get(rule, "schema", ".*") + match_entire(schema_pattern, schema_name) count(rule.privileges) != 0 } @@ -424,17 +447,15 @@ 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", ".*") 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( { @@ -522,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() @@ -539,13 +553,11 @@ 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", ".*") - 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 73% 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 index 4a86af24..4c6e89fa 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/requested_permissions.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/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/trino/requested_permissions_test.rego similarity index 63% 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 0d7214ad..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 @@ -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/trino/util.rego similarity index 80% rename from tests/templates/kuttl/opa-authorization/trino_rules/util.rego rename to tests/templates/kuttl/opa-authorization/trino_rules/trino/util.rego index 9b0978f4..76cee644 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,7 +9,12 @@ package util # # Returns: # result (boolean) +# scope: document +match_entire(`.*`, value) + 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/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 86% rename from tests/templates/kuttl/opa-authorization/trino_rules/verification.rego rename to tests/templates/kuttl/opa-authorization/trino_rules/trino/verification.rego index a5d9568b..9e001fc1 100644 --- a/tests/templates/kuttl/opa-authorization/trino_rules/verification.rego +++ b/tests/templates/kuttl/opa-authorization/trino_rules/trino/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) 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 87a4f695..00000000 --- a/tests/templates/kuttl/opa-authorization/trino_rules/util_test.rego +++ /dev/null @@ -1,13 +0,0 @@ -package util_test - -import data.util - -test_match_entire if { - 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") -}