Use Template UDF for Row-level Filter¶
With template-based row-level filtering, you write the row-filter logic once as a Template UDF in Ranger, and row-filter policies refer to it. For each table that has a template row-filter policy, PolicySync fills the template with the principals of the policy items, creates one row-filter function for that table, and attaches it as the table's row filter.
This approach provides:
- One template for many tables, even when the tables name their columns differently
- No hand-written SQL in policies: each policy item names a template, one of its conditions, and the table columns to use
- Template edits that reach every table using the template, without saving any policy
- Fail-closed behavior: if a table's filter cannot be generated, PolicySync leaves the previous filter in place and withholds the table's own grants (for access policies that cover a whole schema, see Limitations)
How it works¶
- You create a Template UDF (
udfType: 3) in Ranger. It declares itsparameters(name and type of each column value it receives), itsconditionNames(named branches such asCONDITION_US), and a body (udfText) with placeholders. - Each row-filter policy item references the template, one of its conditions (
condition_name), and the tablecolumnsto bind to the parameters, in order. - PolicySync renders the template for the table: each referenced condition gets the principals of the items that use it, conditions that no item uses are left out, and the default branch gets every principal of the policy.
- PolicySync creates the function
<table>_row_filterin the table's schema and attaches it withSET ROW FILTER, before it grants access to the table.
Which row-filter mode to use¶
| Mode | Use it when | Configuration |
|---|---|---|
| Native row filter | Each policy has its own SQL filter expression | CONNECTOR_DATABRICKS_UNITY_CATALOG_ENABLE_ROW_FILTER |
| Reusable UDF | A stable master UDF reads an entitlement table and dispatches to sub-UDFs | CONNECTOR_DATABRICKS_UNITY_CATALOG_ENABLE_REUSABLE_MASTER_UDF_RLS |
| Template UDF (this page) | The same filter logic, with different principals per condition, applies to many tables | CONNECTOR_DATABRICKS_UNITY_CATALOG_ENABLE_TEMPLATE_BASED_ROW_FILTER |
Template-based row filtering has its own flag and does not need CONNECTOR_DATABRICKS_UNITY_CATALOG_ENABLE_ROW_FILTER. A table uses one mode at a time; a service can use native and template row filters on different tables. Template row filters are native Unity Catalog row filters: view-based (secure view) row filtering does not support template policies, so set CONNECTOR_DATABRICKS_UNITY_CATALOG_ENABLE_VIEW_BASED_ROW_FILTER to "false" (see Prerequisites).
Prerequisites¶
- Column loading. PolicySync checks every bound column against the table's columns, so column metadata must be loaded:
CONNECTOR_DATABRICKS_UNITY_CATALOG_LOAD_COLUMNSmust be"true"(the default). Without it, every template row-filter policy fails withTEMPLATE_COLUMNS_NOT_LOADED. - No view-based row filtering.
CONNECTOR_DATABRICKS_UNITY_CATALOG_ENABLE_VIEW_BASED_ROW_FILTERmust be"false"(its default in Privacera Manager is"true"). Secure views do not recognize template references, so a secure view must not be built from a template row-filter policy. - UDF UI in the Portal. Set
PORTAL_UDF_SUPPORTED_SERVICESand enable the User Defined Functions module as described in Portal: UDF-supported services and step 5 of Enable reusable master UDF RLS.
Enable template-based row filters (connector)¶
These settings are Databricks Unity Catalog connector variables in Privacera Manager.
| Variable | Connector property | Default | Description |
|---|---|---|---|
CONNECTOR_DATABRICKS_UNITY_CATALOG_ENABLE_TEMPLATE_BASED_ROW_FILTER | ranger.policysync.connector.0.enable.template.based.row.filter | false | Set to "true" to enable template-based row filters. |
CONNECTOR_RANGER_ENABLE_IMPLICIT_UDF_ENRICHER | policysync.ranger.enable.implicit.udf.enricher | false | Set to "true". PolicySync receives the Template UDFs from Ranger only when this is enabled. |
CONNECTOR_DATABRICKS_UNITY_CATALOG_LOAD_COLUMNS | ranger.policysync.connector.0.load.columns | true | Keep "true"; bound columns are validated against the table's columns. |
CONNECTOR_DATABRICKS_UNITY_CATALOG_ENABLE_VIEW_BASED_ROW_FILTER | ranger.policysync.connector.0.enable.view.based.row.filter | true | Set to "false"; template row filters are native row filters only. |
Template row-filter policies while the flag is off
If a table has a template row-filter policy while CONNECTOR_DATABRICKS_UNITY_CATALOG_ENABLE_TEMPLATE_BASED_ROW_FILTER is "false", PolicySync does not apply it and withholds the table's own grants (reason code TEMPLATE_RLS_DISABLED), so those grants never apply without the filter. For access policies that cover a whole schema, see Limitations.
On Self-Managed Privacera Manager, use the procedure below.
-
SSH to the instance where Privacera Manager is installed.
-
Run the following command to open the
.ymlfile to be edited.Multiple connector instances
If you have multiple connectors, replace
instance1with the appropriate connector instance name.Bash -
Set the following properties:
-
Once the properties are configured, run the following commands to update your Privacera Manager platform instance:
Step 1 - Setup which generates the helm charts. This step usually takes few minutes.
Step 2 - Apply the Privacera Manager helm charts. Step 3 - (Optional) Post-installation step which generates Plugin tar ball, updates Route 53 DNS and so on. This step is not required if you are updating only connector properties.
Create a template¶
Create the template from the User Defined Functions page in the Privacera Portal (UDF type Template), or with the Ranger UDF API.
| Field | Description |
|---|---|
name | Template name, unique per Ranger service (case-insensitive), at most 512 characters. Policies refer to the template by this name. Use identifier-safe names: the name appears in audits and errors. |
udfType | 3 (Template). |
parameters | Ordered list of { "name": ..., "type": ... }. These are the arguments of the generated function; the body refers to them by name. Write each type the way Unity Catalog reports the column type, for example STRING, INT, DATE, DECIMAL(10,2). Types are compared as written, without synonyms: a foreign (federated) table can report a column differently, for example integer for a Glue int column, so declare INTEGER there. |
conditionNames | The named conditions a policy item can choose from. Each name starts with CONDITION and uses uppercase letters, digits, _ and -, for example CONDITION_US. |
udfText | The template body: a boolean SQL expression, described below. |
Template body¶
The body is the SQL expression the generated function returns. It is not a CREATE FUNCTION statement: PolicySync builds the function around it.
- Wrap each condition's branch in
<CONDITION_X>…</CONDITION_X>tags, one block per name inconditionNames. Blocks that no policy item references are removed from the generated function. - Put exactly one
${PRINCIPAL_LIST}inside each block. PolicySync replaces it with the principals of the items that reference that condition, as a quoted, comma-separated list. - Use
${ALL_PRINCIPAL_LIST}(required) outside the blocks. PolicySync replaces it with every principal of the policy. Use it for the default branch, which decides what a caller who matches none of the template's conditions sees. - Refer to the table's columns only through the parameter names. The body can read other tables (for example a consent table) by their fully qualified names.
Callers who match no condition
The default branch decides what a caller sees when they match none of the template's conditions. The examples below return TRUE there, so such a caller sees all rows; whether they can read the table at all is still decided by access policies. Return FALSE instead if such a caller must see no rows.
Example: filter by country¶
Template with one parameter and two conditions:
Example: match groups and roles¶
current_user() returns the user, never a group. To let a condition match groups and roles as well as users, check membership in the body:
Service principals can be policy item principals: they run as themselves, so current_user() returns their application ID.
Reference a template from a row-filter policy¶
In a row-filter policy on the table, set each policy item's row-filter expression (rowFilterInfo.filterExpr) to a JSON reference instead of SQL:
| JSON | |
|---|---|
| Key | Description |
|---|---|
type | Always template. |
template | Name of the Template UDF. |
condition_name | One of the template's conditionNames. The item's users, groups and roles are filled into that condition's ${PRINCIPAL_LIST}. |
columns | The table's columns, bound to the template's parameters by position. The count must equal the number of parameters, and each column's type must match its parameter's type. |
Example row-filter policy with two items on sales.orders:
Rules for a table's row-filter policy:
- All items reference the same template, and all items use the same
columns. - Template items cannot be mixed with SQL row-filter items on the same table.
- A principal can appear in only one condition. Several items can reference the same condition; their principals are merged.
- Another table can use the same template with its own column names, for example
"columns":["region_code"], as long as the column types match the parameters.
What PolicySync creates in Unity Catalog¶
For the example above, PolicySync runs two statements on cat.sales.orders:
- Name and location. The function is
<table>_row_filterin the table's own schema. For foreign catalogs it is created in the Privacera-managed catalog that holds the connector's functions for that catalog. - Ownership marker. The
COMMENTmarks the function as managed by PolicySync and records a hash of what was applied. PolicySync never replaces or drops a function of that name without the marker; seeTEMPLATE_FUNCTION_NAME_CONFLICT. - Principals. Principal names are the names PolicySync uses for them in Unity Catalog (for users, the name
current_user()returns), sorted, so the same input always produces the same function. - No churn. When the rendered function is unchanged, PolicySync runs no DDL. A body edit inside one condition changes only the tables whose policies use that condition.
- Attach before grant. The row filter is attached before PolicySync grants access to the table, so the table's grants never apply without its filter.
Do not edit the generated function
Changes made to <table>_row_filter outside PolicySync are put back at the next periodic permission sync (CONNECTOR_DATABRICKS_UNITY_CATALOG_PERMISSION_SYNC_INTERVAL), or earlier when a policy or template change re-renders the table's function. If the function was replaced by one without the PolicySync marker, PolicySync does not overwrite it and fails closed instead. This repair requires the JDBC permission load (CONNECTOR_DATABRICKS_UNITY_CATALOG_USE_DATABASE_CONNECTION_API: "false", the default), which is the recommended setting for template row filters.
Lifecycle¶
| Change | What PolicySync does in Unity Catalog |
|---|---|
| Template row-filter policy created | Creates <table>_row_filter and attaches it (SET ROW FILTER), then grants access. |
| Item added or removed, principals changed | Re-renders the function and replaces it (CREATE OR REPLACE FUNCTION). The attached filter stays in place. A condition left with no items is removed from the function. |
| Template body edited | Every table using the template is re-applied, without any policy save, within the Ranger plugin refresh interval. Only tables whose rendered function changed run DDL. One TEMPLATE_UPDATE_RESPONSE audit event reports the result; see Audits of a template update. |
Template renamed, parameters changed, or a referenced condition removed | Rejected by Ranger while a policy references the template (TEMPLATE_IN_USE). To change the signature, create a new template and move the policies to it. A referenced template cannot be deleted. |
| Policy removed or disabled (no template items left on the table) | Detaches the filter (DROP ROW FILTER) and drops the function (DROP FUNCTION IF EXISTS). |
| Table switched between native and template row filters | The new filter replaces the old one with a single SET ROW FILTER, then the old function is dropped. |
| Table dropped and recreated | Unity Catalog drops the attachment with the table but keeps the function. PolicySync attaches the filter to the new table before it grants access again. |
| Function edited, dropped, or filter detached outside PolicySync | Put back at the next periodic permission sync, or earlier on a policy or template change. |
Audits of a template update¶
A template can be used by thousands of tables. Two PolicySync audit events show what a template change did: each table's ACCESS event names the template and its version, and one TEMPLATE_UPDATE_RESPONSE event per changed template summarizes all of its tables.
Template version on each table's ACCESS event¶
These ACCESS events of a template row filter carry the template in extraInfo.udf_template:
- Creating or attaching the filter,
COMPLETEDorFAILED. - Dropping the filter when the table no longer uses the template: its policy was removed, or the table switched to another row-filter mode.
A drop of the old function that PolicySync puts off to a later apply, because it could not yet confirm the function is its own or the first drop failed, does not name the template.
| Field | Type | Description |
|---|---|---|
extraInfo.udf_template.name | String | The template. |
extraInfo.udf_template.version | Integer | The template's version in Ranger. On a COMPLETED event, the version the table's function was rendered from. On a FAILED event, the version PolicySync tried to apply; the table keeps its previous filter. On a drop event, the template's current version. |
extraInfo.udf_template.updateTime | String | When that version was saved in Ranger, in the same format as evtTime. |
versionandupdateTimeare the template's own values in Ranger, not the version of the whole UDF catalog. A value Ranger does not provide is left out; a template that does not exist has onlyname.- A
FAILEDevent names the template only when the table's policy references exactly one. A policy that references two templates (TEMPLATE_MIXED_ITEMS) gives aFAILEDevent withoutudf_template. - The
template,binding, andapplyModefields are unchanged.
| JSON | |
|---|---|
A table whose rendered function did not change runs no DDL, so it gets no new ACCESS event. Its last ACCESS event still shows the version last applied to it, and the template update counts it as unchanged.
TEMPLATE_UPDATE_RESPONSE summary¶
When a template is edited, PolicySync re-applies every table that uses it in one run (changelog type TEMPLATE_UDF_REAPPLY). At the end of the run it sends one TEMPLATE_UPDATE_RESPONSE event per changed template, which shows whether the change reached every table.
- It is sent only for this run: not for a policy change, and not for a template that no table uses.
- Like
POLICY_RESPONSE, it is sent only when the change processor progress report is on, which it is by default:
| Variable | Connector property | Default | Description |
|---|---|---|---|
CONNECTOR_DATABRICKS_UNITY_CATALOG_CHANGEPROCESSOR_PROGRESS_REPORT_TRACKER_ENABLE | ranger.policysync.connector.0.changeprocessor.progress.report.tracker.enable | true | Sends TEMPLATE_UPDATE_RESPONSE, and the CHANGELOG (queued, started, completed or failed, skipped) and POLICY_RESPONSE events of every changelog, not only of template updates. Set to "false" to stop all three. It does not stop PROGRESS events, which other settings control. |
Set it in the connector instance's vars.connector.databricks.unity.catalog.yml and run the Privacera Manager update, as in Enable template-based row filters. Its default follows the Privacera Manager-wide CONNECTOR_CHANGEPROCESSOR_PROGRESS_REPORT_TRACKER_ENABLE.
The event's fields:
| Field | Type | Description |
|---|---|---|
eventType | String | TEMPLATE_UPDATE_RESPONSE |
status | String | COMPLETED when no table failed, FAILED when every table failed, otherwise GRANT_PARTIALLY_APPLIED. |
msg | String | A one-line summary of the counts. |
changeLogType / changeLogId | String / Integer | TEMPLATE_UDF_REAPPLY, and the ID of the run. |
timeTakenMs | Integer | How long the run took, in milliseconds. |
extraInfo.udf_template | Object | name, version, and updateTime of the template version that was applied. |
extraInfo.tableCount.attached | Integer | Tables that use the template: recreated + unchanged + failed. |
extraInfo.tableCount.recreated | Integer | Tables whose function was re-created and whose filter was applied. |
extraInfo.tableCount.unchanged | Integer | Tables whose rendered function did not change, so no DDL ran. |
extraInfo.tableCount.failed | Integer | Tables whose re-apply did not complete. Most keep their previous filter; a table whose new filter was attached before a later statement failed, or whose apply could not be recorded, already has the new one. |
extraInfo.response[] | Array | The failures, as response codes. Absent when no table failed. |
The event has no zoneName: templates are not in a security zone.
response[] groups the failed tables like any other event: by code, origin, and serviceCode, at most ten entries, highest count first.
- A transient Databricks failure is
5001, which is worth retrying. - A table whose re-apply stopped before its row filter ran, or whose filter applied but could not be recorded, has no code of its own and is also counted as
5001.
Find the failed tables¶
The summary does not list the tables. To find them, search the ACCESS events with:
- the same
connectorandchangeLogIdas the summary, statusFAILED,- the summary's template in
extraInfo.udf_template.name. The same run also applies other templates changed with it, and retries tables pending from an earlier failure, so match the name.
Each event has the table, and its reason code in extraInfo.response[].
This search can find fewer tables than failed:
- A table counted under
5001with no code of its own may have noFAILEDACCESSevent. - A table whose policy references more than one template fails with
4005TEMPLATE_MIXED_ITEMS, and its event has noudf_template. Find these with a second search: sameconnectorandchangeLogId,statusFAILED,extraInfo.response[].code4005, and noextraInfo.udf_template. Each one is counted in the summary of every changed template the table uses.
Do not search for every FAILED event without udf_template. The run re-applies each table's whole permissions, so other grants that fail in it, such as a withheld grant now failing with 4503, are FAILED ACCESS events in the same changelog that no summary counts.
When a failed table is applied again¶
- On the next edit of any template. Each run also retries the tables still pending from an earlier failure, without counting them in its summary.
- When the table's row-filter policy changes. To retry a table now, save its row-filter policy again.
- On the periodic permission sync, only with the JDBC permission load (
CONNECTOR_DATABRICKS_UNITY_CATALOG_USE_DATABASE_CONNECTION_API: "false", the default), and only in two cases:CREATE OR REPLACE FUNCTIONcompleted and a later statement, such asSET ROW FILTER, failed, on a table that already had a template filter. The function's hash then differs from the one PolicySync recorded.- The sync found the filter changed outside PolicySync, and its repair failed. PolicySync then has no recorded hash for the table, so every later sync retries it until an apply succeeds.
The periodic sync does not retry any other failure, because Unity Catalog still matches what PolicySync recorded. That includes a failure found before any DDL ran, such as a failed check of the function's ownership (4002 with no serviceCode), and Databricks rejecting CREATE OR REPLACE FUNCTION itself. With the API permission load, it retries no failed table.
What the summary does not cover¶
- Several edits of the same template before the run starts: one run applies the latest version, and the summary reports that version.
- An edit that arrives while a long run is in progress: some tables are rendered from the earlier version and some from the later one. The summary reports the highest version, and the next run applies the latest version to every table.
- A run that fails gets no summary. Normally, so does a run interrupted by a connector restart: it is queued again, but starts before the connector has loaded its tables and finds nothing to re-apply.
- In both cases the tables not yet re-applied keep their previous filter until the next edit of any template, which re-applies them without counting them in its summary. An edit whose tables PolicySync had not looked up yet is applied, and summarized, in that later run.
- A table that stops using the template during the run is not counted.
Errors and fail-closed behavior¶
Errors when saving in Ranger¶
Ranger rejects an invalid template or policy with HTTP 400. The error code is in messageList[0].name and the details in msgDesc.
| Code | When |
|---|---|
TEMPLATE_NOT_FOUND | The policy references a template that does not exist or is not of type Template. |
UNKNOWN_CONDITION | condition_name is not one of the template's conditionNames. |
TEMPLATE_MIXED_ITEMS | Template items are mixed with SQL items, or items reference different templates. |
COLUMN_BINDING_INVALID | columns is missing, its length differs from the number of parameters, it has blank or duplicate entries, or items disagree on columns. |
TEMPLATE_BODY_INVALID | The body's condition tags do not match conditionNames, a block has no or several ${PRINCIPAL_LIST}, ${ALL_PRINCIPAL_LIST} is missing, or ${PRINCIPAL_LIST} is outside a block. |
TEMPLATE_IN_USE | Renaming the template, changing its parameters, or removing a condition while a policy references it. |
Errors from the connector¶
Errors that depend on the table are found when PolicySync applies the policy. In every case PolicySync fails closed: the previous row filter stays in place, and PolicySync withholds the table's own grants (for access policies that cover a whole schema, see Limitations).
- Most errors are found before any DDL runs.
UNDECLARED_COLUMNandDDL_FAILEDcome from Databricks rejecting the DDL. - After you fix the cause, the table is applied again on its next policy change or the next edit of its template. To apply it now, save its row-filter policy again. The periodic permission sync retries only some failures; see When a failed table is applied again.
- For
TEMPLATE_COLUMNS_NOT_LOADED, the column metadata arrives with the next resource sync.
The reason code is in the PolicySync audits, in extraInfo.response[] of the failed ACCESS event and of the policy's POLICY_RESPONSE event, with details in the event's message. See Codes in the PolicySync audits.
| Code | Cause | Fix |
|---|---|---|
PARAM_NAME_MISMATCH | A bound column is not a column of the table. | Correct columns in the policy items. |
PARAM_TYPE_MISMATCH | A bound column's type differs from its parameter's type. | Bind a column of the declared type, or use a template whose parameter type matches. |
PRINCIPAL_OVERLAP | The same principal is in two conditions. | Keep each principal in one condition. |
TEMPLATE_NOT_FOUND | PolicySync has not received the template (for example, right after it was created). | Wait for the next Ranger refresh; check CONNECTOR_RANGER_ENABLE_IMPLICIT_UDF_ENRICHER. |
UNKNOWN_CONDITION | The condition is not in the template PolicySync has. | Check the condition name and the template's conditionNames. |
TEMPLATE_MIXED_ITEMS | Template items are mixed with SQL items, or items reference different templates. | Use one template for all items of the table's row-filter policy. |
COLUMN_BINDING_INVALID | columns is missing, has the wrong count, a blank or duplicate entry, or items disagree on columns. | Correct columns in the policy items so every item binds the same columns, one per parameter. |
PLACEHOLDER_UNFILLED | A placeholder was left in the rendered body, or a referenced condition has no principals. | Check the template body and the policy items. |
TEMPLATE_RENDER_FAILED | The template could not be rendered, for example an item uses the public group. | Read the message; replace public with named groups. |
TEMPLATE_COLUMNS_NOT_LOADED | The table has no column metadata. | Set CONNECTOR_DATABRICKS_UNITY_CATALOG_LOAD_COLUMNS to "true" and wait for the next resource sync. |
TEMPLATE_FUNCTION_NAME_CONFLICT | A function named <table>_row_filter exists without the PolicySync ownership marker. | Rename or drop that function if it is not needed. PolicySync never replaces or drops it. |
TEMPLATE_RLS_DISABLED | A template row-filter policy exists but the connector flag is off. | Set CONNECTOR_DATABRICKS_UNITY_CATALOG_ENABLE_TEMPLATE_BASED_ROW_FILTER to "true". |
UNDECLARED_COLUMN | Databricks rejected the function: the body references a column that is neither a parameter nor a column of a table it reads. | Use parameter names for the table's columns. |
DDL_FAILED | Databricks rejected CREATE FUNCTION or SET ROW FILTER for another reason. | Read the Databricks error in the audit message. |
Codes in the PolicySync audits¶
A failure found when PolicySync applies the policy is an entry in extraInfo.response[] of the failed ACCESS event and of the policy's POLICY_RESPONSE event: a code from 4001 to 4014 (VALIDATION, not worth retrying), with origin PRIVACERA.
DDL_FAILEDandUNDECLARED_COLUMNcome from Databricks rejecting a statement, and carry the Databricks error condition asserviceCode. A transient Databricks failure is5001SYSTEM_ERRORinstead, which is worth retrying.- A save that Ranger rejects (Errors when saving in Ranger) is answered by the Ranger API and is not in the audits.
code | strCode | Category | Meaning |
|---|---|---|---|
4001 | TEMPLATE_NOT_FOUND | VALIDATION | The referenced template is not among the templates PolicySync has received, or is not a Template UDF |
4002 | DDL_FAILED | VALIDATION | Databricks rejected the CREATE FUNCTION or SET ROW FILTER statement. serviceCode carries the Databricks error condition when there is one. Also reported when the connector could not confirm that it owns the template function; then no statement ran and there is no serviceCode. The periodic permission sync does not retry it: the table is applied again on its next policy change or template edit, or when its row-filter policy is saved again |
4003 | UNKNOWN_CONDITION | VALIDATION | condition_name is not one of the template's conditions |
4004 | PRINCIPAL_OVERLAP | VALIDATION | The same principal is assigned to more than one condition |
4005 | TEMPLATE_MIXED_ITEMS | VALIDATION | Template items are mixed with SQL row-filter items, or with another template, on the same table |
4006 | COLUMN_BINDING_INVALID | VALIDATION | columns is missing, has the wrong length, has blank or duplicate entries, or differs between the items of one policy |
4007 | PARAM_NAME_MISMATCH | VALIDATION | A bound column is not a column of the table |
4008 | PARAM_TYPE_MISMATCH | VALIDATION | A bound column's type differs from the template parameter's type |
4009 | PLACEHOLDER_UNFILLED | VALIDATION | A placeholder was left unfilled, or a referenced condition has no principals |
4010 | TEMPLATE_RENDER_FAILED | VALIDATION | The template could not be rendered: a malformed body, an unsupported principal such as the public group, or an invalid parameter definition |
4011 | UNDECLARED_COLUMN | VALIDATION | Databricks rejected the function because the body references a column that is not a declared parameter. serviceCode carries the Databricks error condition when there is one |
4012 | TEMPLATE_RLS_DISABLED | VALIDATION | The table has a template row-filter policy, but template-based row filtering is turned off on the connector |
4013 | TEMPLATE_FUNCTION_NAME_CONFLICT | VALIDATION | A function named <table>_row_filter exists that PolicySync did not create |
4014 | TEMPLATE_COLUMNS_NOT_LOADED | VALIDATION | Column metadata is not loaded for the table, so the column binding and parameter types cannot be checked |
For the other fields of an entry, see Response codes in Policy Tracing.
Ranger UDF API¶
Replace <ranger-host> with your Ranger admin host and use valid credentials. serviceName must match your Databricks Unity Catalog service in Ranger (commonly privacera_databricks_unity_catalog).
| Operation | HTTP |
|---|---|
| Create or update a template | PUT https://<ranger-host>/service/udf/service/<service-name>/name/<udf-name> |
| Get a template | GET https://<ranger-host>/service/udf/service/<service-name>/name/<udf-name> |
| List its conditions | GET https://<ranger-host>/service/udf/service/<service-name>/name/<udf-name>/conditions |
| Delete a template | DELETE https://<ranger-host>/service/udf/service/<service-name>/name/<udf-name> (rejected while a policy references it) |
Limitations¶
- Principals only. Conditions match the caller with
current_user()(and group membership when the body checks it). Attribute and tag macros are not supported. - No
publicgroup. An item that uses thepublicgroup fails withTEMPLATE_RENDER_FAILED. - One template per table. All template items of a table's row-filter policy reference the same template.
- Fail-closed applies to the table's own grants. If a table's template filter fails, PolicySync withholds the grants on that table. An access policy that covers a whole schema (
table: *) is granted asSELECTon the schema, and that schema-level grant still reaches the table without a filter. For tables protected by a row filter, list the tables explicitly in the access policy. - Reusable UDF to template. A table cannot switch directly from a reusable master UDF filter to a template filter. Remove the master UDF policy from the table and sync, then add the template policy and sync again; restrict access to the table between the two syncs.
- Changes made outside PolicySync are repaired at the next periodic permission sync, not immediately: PolicySync checks the attached filter and the function's marker during that sync, with one query per schema that contains tables with a template filter (no extra queries on other applies). Until then the table is filtered by whatever is in Unity Catalog; if the filter was detached, the table has no row filter. To detect a body edit, PolicySync records the function's definition at the first permission sync after it creates or updates the function, and compares later definitions with that record. An edit made before that first permission sync becomes part of the record and is not detected. Restrict who can modify functions and row filters in the table's schema.
- JDBC permission load only. Repair of changes made outside PolicySync is supported only with the JDBC permission load (
CONNECTOR_DATABRICKS_UNITY_CATALOG_USE_DATABASE_CONNECTION_API: "false", the default), which is recommended for template row filters. With the API permission load ("true"), template filters are still applied on every policy or template change, but changes made outside PolicySync are not repaired until the next such change.
- Prev topic: Use Reusable UDF for Row-level Filter
- Next topic: Troubleshooting