Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions rust/operator-binary/src/authorization/opa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ pub struct TrinoOpaConfig {
/// `http://localhost:8081/v1/data/trino/rowFilters` - if not set,
/// no row filtering will be applied
pub(crate) row_filters_connection_string: Option<String>,
/// URI for fetching column masks, e.g.
/// `http://localhost:8081/v1/data/trino/columnMask` - if not set,
/// no masking will be applied
pub(crate) column_masking_connection_string: Option<String>,
/// URI for fetching columns masks in batches, e.g.
/// `http://localhost:8081/v1/data/trino/batchColumnMasks` - if not set,
/// column-masking-uri will be used for getting column masks in parallel
pub(crate) batched_column_masking_connection_string: Option<String>,
/// Whether to allow permission management (GRANT, DENY, ...) and
/// role management operations - OPA will not be queried for any
/// such operations, they will be bulk allowed or denied depending
Expand Down Expand Up @@ -65,12 +65,12 @@ impl TrinoOpaConfig {
OpaApiVersion::V1,
)
.await?;
let column_masking_connection_string = opa_config
let batched_column_masking_connection_string = opa_config
.full_document_url_from_config_map(
client,
trino,
// Sticking to https://github.com/trinodb/trino/blob/455/plugin/trino-opa/src/test/java/io/trino/plugin/opa/TestOpaAccessControlDataFilteringSystem.java#L47
Some("columnMask"),
// Sticking to https://github.com/trinodb/trino/blob/455/plugin/trino-opa/src/test/java/io/trino/plugin/opa/TestOpaAccessControlDataFilteringSystem.java#L48
Some("batchColumnMasks"),
OpaApiVersion::V1,
)
.await?;
Expand All @@ -89,7 +89,7 @@ impl TrinoOpaConfig {
non_batched_connection_string,
batched_connection_string,
row_filters_connection_string: Some(row_filters_connection_string),
column_masking_connection_string: Some(column_masking_connection_string),
batched_column_masking_connection_string: Some(batched_column_masking_connection_string),
allow_permission_management_operations: true,
tls_secret_class,
})
Expand All @@ -113,10 +113,10 @@ impl TrinoOpaConfig {
Some(row_filters_connection_string.clone()),
);
}
if let Some(column_masking_connection_string) = &self.column_masking_connection_string {
if let Some(batched_column_masking_connection_string) = &self.batched_column_masking_connection_string {
config.insert(
"opa.policy.column-masking-uri".to_string(),
Some(column_masking_connection_string.clone()),
"opa.policy.batch-column-masking-uri".to_string(),
Some(batched_column_masking_connection_string.clone()),
);
}
if self.allow_permission_management_operations {
Expand Down
6 changes: 3 additions & 3 deletions rust/operator-binary/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2064,8 +2064,8 @@ mod tests {
"http://simple-opa.default.svc.cluster.local:8081/v1/data/my-product/rowFilters"
.to_string(),
),
column_masking_connection_string: Some(
"http://simple-opa.default.svc.cluster.local:8081/v1/data/my-product/columnMask"
batched_column_masking_connection_string: Some(
"http://simple-opa.default.svc.cluster.local:8081/v1/data/my-product/batchColumnMasks"
.to_string(),
),
allow_permission_management_operations: true,
Expand Down Expand Up @@ -2167,7 +2167,7 @@ mod tests {
assert!(access_control_config.contains("foo.bar=true"));
assert!(access_control_config.contains("opa.allow-permission-management-operations=false"));
assert!(access_control_config.contains(r#"opa.policy.batched-uri=http\://simple-opa.default.svc.cluster.local\:8081/v1/data/my-product/batch-new"#));
assert!(access_control_config.contains(r#"opa.policy.column-masking-uri=http\://simple-opa.default.svc.cluster.local\:8081/v1/data/my-product/columnMask"#));
assert!(access_control_config.contains(r#"opa.policy.batch-column-masking-uri=http\://simple-opa.default.svc.cluster.local\:8081/v1/data/my-product/batchColumnMasks"#));
assert!(access_control_config.contains(r#"opa.policy.row-filters-uri=http\://simple-opa.default.svc.cluster.local\:8081/v1/data/my-product/rowFilters"#));
assert!(access_control_config.contains(r#"opa.policy.uri=http\://simple-opa.default.svc.cluster.local\:8081/v1/data/my-product/allow"#));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,18 @@
},

"GetColumnMask": {
"type": "object",
"oneOf": [
{
"$ref": "#/$defs/SingleColumnMask"
},
{
"$ref": "#/$defs/BatchColumnMasks"
}
]
},

"SingleColumnMask": {
"type": "object",
"properties": {
"operation": {
Expand Down Expand Up @@ -562,6 +574,55 @@
"required": ["operation", "resource"]
},

"BatchColumnMasks": {
"type": "object",
"properties": {
"operation": {
"const": "GetColumnMask"
},
"filterResources": {
"type": "array",
"items": {
"type": "object",
"properties": {
"column": {
"type": "object",
"properties": {
"catalogName": {
"type": "string"
},
"schemaName": {
"type": "string"
},
"tableName": {
"type": "string"
},
"columnName": {
"type": "string"
},
"columnType": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"catalogName",
"schemaName",
"tableName",
"columnName",
"columnType"
]
}
},
"additionalProperties": false,
"required": ["column"]
}
}
},
"additionalProperties": false,
"required": ["operation", "filterResources"]
},

"GetRowFilters": {
"type": "object",
"properties": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# - allow
# - batch
# - columnMask
# - batchColumnMasks
# - rowFilters
# These rules use the rules and functions in requested_permission.rego
# and actual_permissions.rego to calculate the result.
Expand Down Expand Up @@ -302,6 +303,88 @@ columnMask := column_mask if {
column_mask := {"expression": column.mask}
}

# METADATA
# description: |
# Entry point for fetching column masks in batch, configured in the
# Trino property `opa.policy.batch-column-masking-uri`.
#
# The input has the following form:
#
# {
# "action": {
# "operation": "GetColumnMasks",
# "filterResources": [{
# "column": {
# "catalogName": "catalog",
# "schemaName": "schema",
# "tableName": "table",
# "columnName": "column",
# }},
# {"column": ...},
# ...
# ],
# },
# "context": {
# "identity": {
# "groups": ["group1", ...],
# "user": "username",
# },
# "softwareStack": {"trinoVersion": "455"},
# }
# }
#
# The batchColumnMask rule queries the column constraints in the
# Trino policies for each of the resources in the "filterResources"
# list of the request and returns a list of viewExpressions, containing
# the column mask if any set and optionally the identity for the mask
# evaluation, and the index of the corresponding resource in the
# "filterResources" list of the request.
# A column mask is an SQL expression,
# e.g. "'XXX-XX-' + substring(credit_card, -4)".
# entrypoint: true
batchColumnMasks contains column_mask if {
input.action.operation == "GetColumnMask"
some index, resource in input.action.filterResources

column := column_constraints(
resource.column.catalogName,
resource.column.schemaName,
resource.column.tableName,
resource.column.columnName,
)

is_string(column.mask)
is_string(column.mask_environment.user)

column_mask := {
"index": index,
"viewExpression": {
"expression": column.mask,
"identity": column.mask_environment.user,
},
}
}

batchColumnMasks contains column_mask if {
input.action.operation == "GetColumnMask"
some index, resource in input.action.filterResources

column := column_constraints(
resource.column.catalogName,
resource.column.schemaName,
resource.column.tableName,
resource.column.columnName,
)

is_string(column.mask)
is_null(column.mask_environment.user)

column_mask := {
"index": index,
"viewExpression": {"expression": column.mask},
}
}

# METADATA
# description: |
# Entry point for fetching row filters, configured in the Trino
Expand Down
Loading