Configure Principal Directory¶
This property enables a connector-owned principal directory table in Snowflake. When enabled, masking and row-filter policies whose conditions reference the caller's group/role membership or attributes are translated into a constant-size sub-query against the directory table, instead of inlining the resolved list of users into the policy.
Applies to policy conditions only
The directory translation applies only to ABAC macros placed in a policy's condition (the policy-item access/expression condition). Macros used inside a custom masking value or inside a row-filter filter expression are not translated — for those, the generated SQL DDL still inlines the resolved user list (the existing behavior).
Overview¶
By default, when a masking or row-filter policy uses a principal-attribute condition (for example IS_IN_GROUP('sales') or USER.level > 5), the connector resolves the condition to the matching users and inlines that user list into the generated Snowflake policy (for example CURRENT_USER IN ('u1','u2', … )). For large groups/roles this produces very large policy bodies that must be regenerated on every membership change, and can exceed Snowflake's statement-size limits.
With the principal directory enabled, the connector instead:
- Creates a table
PRIV_PRINCIPAL_DIRECTORYin thePUBLICschema of its home database (defaultPRIVACERA_DB) and keeps it in sync with the Ranger principal (user, group, role) attributes and membership. - Emits the policy condition as a constant-size
EXISTS(...)sub-query against that directory, evaluated perCURRENT_USER()at query time.
Only principals with attributes or membership are stored
The directory holds a row only for principals that carry data a condition can match — a user that has one or more attributes, or a group/role that has members or attributes. A principal with no attributes and no membership contributes no rows, so the directory stays compact. A user's group and role memberships are recorded on the containing group or role, not on the user's own rows.
Benefits¶
- Constant-size policy SQL — the generated masking/row-filter policy no longer grows with the number of users, and does not need to be rewritten when a principal's membership or attributes change (only the directory rows change).
- Correct for transitive roles — role membership is resolved transitively (nested roles and group-in-role).
- No regression — anything the directory cannot translate falls back to the existing inline path automatically.
Supported conditions¶
The directory translation applies to the following Ranger ABAC macros and expression variables:
IS_IN_GROUP,IS_IN_ANY_GROUP,IS_NOT_IN_ANY_GROUP,HAS_UG_ATTRIS_IN_ROLE,IS_IN_ANY_ROLE,IS_NOT_IN_ANY_ROLE,HAS_UR_ATTRHAS_USER_ATTRUSER.<attr>typed comparisons (==,!=,>,<,>=,<=)
Fallback to the inline path
Conditions outside the supported grammar are not translated and automatically fall back to the inline path, so behavior is unchanged for them. This includes the Ranger built-in user attributes _name and _emailAddress (these are computed by Ranger and are not stored in the directory), and dynamic GET_* expressions.
Prerequisites¶
The connector creates and maintains the directory table under the PUBLIC schema of its home database — the CONNECTOR_SNOWFLAKE_JDBC_DB property, default PRIVACERA_DB (see Configuration). That database must already exist and the connector's Snowflake role must be able to create a table in it.
-
Ensure the home database exists. The default
PRIVACERA_DBis created as part of the standard Snowflake prerequisites. If you configure the connector to use a custom database, create that database first and apply the same grants described in the standard Snowflake prerequisites. -
Grant the
CREATE TABLEprivilege on the home database'sPUBLICschema. This is in addition to theUSAGE+CREATE FUNCTIONgrants that the standard prerequisites already apply toPRIVACERA_DB— the standard setup does not grantCREATE TABLE:SQL (Replace
<home-db>withPRIVACERA_DBor your custom database name, and<connector-role>with the connector's Snowflake role, e.g.PRIVACERA_POLICYSYNC_ROLE.)USAGEis required in addition toCREATE TABLEWithout
USAGEon both the database and the schema, Snowflake reportsDatabase '<db>' does not exist or not authorizedat startup even whenCREATE TABLEhas been granted — this is Snowflake hiding object existence behind authorization, not a missing table.
End users need no grants on the directory table
The masking/row-filter policies evaluate the directory sub-query with the policy owner's privileges, so the querying users do not need any grant on PRIV_PRINCIPAL_DIRECTORY or its database.
Configuration¶
-
SSH to the instance where Privacera Manager is installed.
-
Run the following command to open the
.ymlfile to be edited.If you have multiple connectors, then replace
instance1with the appropriate connector instance name.Bash Home database (
CONNECTOR_SNOWFLAKE_JDBC_DB)The directory table is created in the
PUBLICschema of the connector's home database, set by theCONNECTOR_SNOWFLAKE_JDBC_DBproperty. It defaults toPRIVACERA_DB; to place the directory in a different database, set it to your custom database name:A custom database must be pre-created and granted the required privileges — see Prerequisites.YAML -
Add the following property:
YAML -
Once the property is 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.
Default
This property is disabled by default. Existing connectors are unaffected until you opt in; enabling it does not change the outcome of policy evaluation — only the form of the generated policy SQL.
Behavior on fresh install, upgrade, and rollback¶
Enabling or disabling the principal directory is a configuration change applied through Privacera Manager; it takes effect after the connector restarts. Once the connector restarts, it automatically converts the already-applied policies into the required form — you do not need to edit or re-publish any Ranger policy. In every case the outcome of policy evaluation is unchanged; only the form of the generated Snowflake SQL (a directory sub-query versus an inline user list) differs.
Fresh install — directory enabled from the start¶
On the first startup with the property enabled, the connector creates the directory table (and a companion metadata table that records a bootstrap-complete marker) and runs a full sync to populate it from the connector's principal store. As policies are synchronized, every masking or row-filter policy whose condition is translatable is applied directly in the directory (EXISTS) form; conditions outside the supported grammar are applied inline. There are no earlier inline policies to convert.
Upgrade — enabling on a connector that already has policies¶
When you enable the property on a connector whose policies were previously applied in the inline form:
- On restart, the connector creates and fully syncs the directory table, the same as a fresh install.
- As part of the same restart, each already-applied masking or row-filter policy whose condition is translatable is converted once into the directory form. Policies that cannot be translated stay inline.
This is a one-time conversion per affected policy; after it completes there is no further churn. While the feature stays enabled, a principal's membership or attribute change updates only the directory rows — the policy SQL is not regenerated.
Rollback — disabling after it was enabled¶
When you disable the property on a connector that has directory-form policies applied:
- On restart, the connector stops bootstrapping and syncing the directory. The directory table is left in place but is no longer maintained; it is not dropped.
- As part of the same restart, each policy currently deployed in the directory form is converted once back into the inline form, so no policy is left evaluating against a directory table that is no longer kept current.
This automatic downgrade is what keeps policy evaluation correct after a rollback. If you do not plan to re-enable the feature and want to remove the directory objects, drop the PRIV_PRINCIPAL_DIRECTORY table together with its companion metadata table; if you enable the feature again later, the connector re-creates and re-syncs both.
Examples¶
Example 1: Condition using HAS_USER_ATTR¶
Policy condition: HAS_USER_ATTR('dept')
Generated (directory) form:
| SQL | |
|---|---|
The predicate matches when the current user has a dept attribute in the directory. It is the same size regardless of how many users hold the attribute, and does not need to be regenerated when users gain or lose it.
Example 2: Masking using a user attribute¶
Policy condition: USER.level > 5
Generated (directory) form:
| SQL | |
|---|---|
The mask applies when the current user's level attribute is greater than 5. Ordering operators (>, <, >=, <=) compare ATTR_VALUE numerically via TRY_CAST(... AS DOUBLE).
- Prev topic: Advanced Configuration