Granular policies allow you to configure row-level security for datasets and objects. They are used by restricted views and object security policies to determine which specific rows or object instances a user has permission to access.
A granular policy is a set of rules and logical operators that compare user attributes, columns or properties, and values to determine which data the user can see. Granular policies are flexible and support a range of comparisons and terms.
Before creating a granular policy, consider the following questions:
We recommend the following guidelines when designing a granular policy:
Below is a list of supported user attributes in granular policies:
ri.multipass..organization.When referencing a user, group, or organization, the policy requires the unique identifier (UUID) in both the policy column and the policy definition. Specifying names instead of IDs is not supported to prevent renaming-related issues.
Avoid using NOT conditions with group, marking, or organization memberships. Using a NOT condition in these circumstances is a misconfiguration. The platform supports scoped tokens, which carry only a subset of a user's permissions. These tokens may lack the attribute the NOT condition checks against, causing the condition to pass and grant more access than intended.
Granular policies support the following comparison types:
Restricted view datasource policies, object security policies, and property security policies for Object Storage v2 object types have additional policy type and comparison operator restrictions.
Policies are defined as templates into which user attributes, group memberships, and data values can be filled. When the consuming application requests data (such as in Contour), the template is converted into a query. This query returns only rows or objects specific to the user's attributes and permissions.
Granular policies have a maximum total comparison weight of 10,000. Weight depends on the values each condition compares, so counting the conditions alone does not tell you whether a policy is within this limit. The same weight calculation applies to restricted views and object security policies.
Each condition compares two values. Identify what type each value is:
Open. The policy comparisons section calls this single-valued.Open and Pending.Use the following table to determine the weight of each condition:
| Condition | Example | Weight |
|---|---|---|
| Comparison without a field | Current user Group IDs intersects the selected groups Policy reviewers and Policy readers. | 0 |
| Field compared with a single value | The current user's User ID equals primary key, or status equals Open. | 1 |
| Field compared with a collection | Current user Group IDs intersects primary key, or status matches any value in the list Open, Pending. | 1,000 |
| Marking condition that references a field | The user satisfies the markings stored in a field. | 3,000 |
| Marking condition without a field | The user satisfies a specified set of markings. | 0 |
When you select specific groups, the editor displays group names, but the policy references the selected groups by their IDs.
For field comparisons, the weight depends on whether the value on the other side is a single value or a collection. This applies regardless of which side of the comparison contains the field. A collection remains a collection even when it contains only one value. Its comparison weight does not depend on how many groups the user belongs to or how many entries the list contains.
A weight of 0 does not mean that a condition is ignored. A condition that uses only user attributes and constants can determine access without reading a row or object property. It is evaluated for the user before the remaining field comparisons.
Add the weights of all conditions, including conditions inside nested All (AND) and Any (OR) groups. Both types of group use addition. A NOT operator adds no weight beyond the condition it contains. The restrictions on negating group, marking, or organization membership still apply.
For property security policies, also account for the combined weight of the object and property security policies.
If you receive weight limit errors when constructing policies, contact Palantir Support for assistance.
When you manage granular policies, consider two goals:
Granular policies introduce a set of assumptions about the data that backs them. Therefore, granular policies will only correctly control access to data as long as these assumptions are true. Consider whether the use case requires building out machinery to ensure that those assumptions hold and data stays secured if those assumptions are broken.
One way to solve this problem is by introducing a step in the pipeline directly upstream of the resource that checks the assumptions made about the data. These checks might include:
event_occurred_in_state has the value NY, another column in the dataset called state_name should have value New York. Have the transform check that this is true before surfacing this data to users.These integrity checks protect the upstream data that the granular policy depends on so that the policy continues to filter rows correctly. They do not extend the policy to downstream outputs or exports. To keep data protected as it flows downstream, pair the granular policy with a marking or Classification-based Access Control on the underlying data. For the full model, see Access control propagation.