Row-Level Policies

Immuta row-level policies compare data values with user metadata at query-time to determine whether or not the querying user should have access to the individual rows of data.

These policies hide entire rows or objects of data based on the policy being enforced; some of these policies require the data to be tagged as well.

How do row-level policies work?

The values contained in one or many columns in the table in question (or a separate joined table) need to be referenced by the policy for its logic to take effect.

For example, consider the policy below:

Only show rows where user is a member of a group that matches the value in the column tagged Department.

The data values (the values in the column tagged Department) are matched against the user attribute (their groups) to determine whether or not rows will be visible to the user accessing the data.

The policy targets columns tagged Department; this means that this policy can be applied globally across all tables and data platforms that have that tag with this single policy rather than having to build a separate policy for individual tables and columns.

Masked columns as input for row-level policies

Public preview: This feature is available to all accounts.

If a global masking policy applies to a column, you can still use that masked column in a global row-level policy.

Consider the following policy examples:

  • Masking policy: Mask values in columns tagged Country for everyone except users in group Admin.

  • Row-level policy: Only show rows where user possesses an attribute in OfficeLocation that matches the value in column tagged Country for everyone.

Both of these policies use the Country tag to restrict access. Therefore, the masking policy and the row-level policy would apply to data source columns with the tag Country for users who are not in the Admin group.

Limitations

Matching

These policies match a user attribute with a row/object/file attribute to determine if that row/object/file should be visible. This process uses a direct string match, so the user attribute would have to match exactly the data attribute in order to see that row of data.

For example, to restrict access to insurance claims data to the state for which the user's home office is located, you could build a policy such as this:

Only show rows where user possesses an attribute in Office Location that matches the value in the column State for everyone except when user is a member of group Legal.

In this case, the Office Location is retrieved by the identity management system as a user attribute or group. If the user's attribute (Office Location) was Missouri, rows containing the value Missouri in the State column in the data source would be the only rows visible to that user.

Minimization

These policies return a limited percentage of the data, which is randomly sampled at query time, but it is the same sample for all the users. For example, you could limit certain users to only 10% of the data. Immuta uses a hashing policy to return approximately 10% of the data, and the data returned will always be the same; however, the exact number of rows exposed depends on the distribution of high cardinality columns in the database and the hashing type available. Additionally, Immuta will adjust the data exposed when new rows are added or removed.

Best practice: row count

Immuta recommends you use a table with over 1,000 rows for the best results when using a data minimization policy.

Time-based restrictions

These policies restrict access to rows/objects/files that fall within the time restrictions set in the policy. If data sources have time-based restriction policies applied to them, queries run against the data sources will only return rows/blobs with dates in their event-time column/attribute from within a certain range.

The time window is based on the event time you select when creating the data source. This value will come from a date/time column in relational sources.

WHERE clause policy

This policy can be thought of as a table "view" created automatically for the user based on the condition of the policy. For example, in the policy below, users who are not members of the Admins group will only see taxi rides where passenger_count < 2.

Only show rows where public.us.taxis.passenger_count <2 for everyone except when user is a member of group Admins.

You can put any valid SQL WHERE clause in the policy. See the Custom WHERE clause functions for a list of custom functions.

Custom functions

It is also possible to use custom functions in custom WHERE row-level policies for more complex use cases.

These wrap Immuta context into free-form SQL logic for the row-level policy. That context can be things like the attributes (@attributeValuesContains()) or groups (@groupsContains()) possessed by the user or the username (@username) - injected into the SQL at runtime.

Avoid referencing explicit column names in custom functions and instead use the @columnTagged('tag name') function in SQL. In doing so, you can avoid having to reference the physical database world with the custom SQL policies and instead continue to target the metadata/tag world.

Avoid using columns masked using randomized response

When building row-level policies with custom SQL statements, avoid using a column that is masked using randomized response in the SQL statement, as this can lead to different behavior depending on whether you’re using the Spark or Snowflake integration and may produce results that are unexpected.

Last updated

Was this helpful?