Fine-Grained Controls for Data

What Are Fine-Grained Controls?

Business requirements often specify that different users should see different portions, or slices, of data. In some cases, the requirement is driven by the sensitive nature of data. For example, company policy might state that each salesperson should be able to access only his or her own salary information. In other cases, the requirement is intended to prevent information overload. For example, each regional sales team within a national organization might be interested in only the sales trend information for their region. Fine-grained access distinctions are frequently based on each user's place in an organizational structure such as a management hierarchy or a product matrix. The visibility of data can depend on a simple, site-specific condition such as a user's security clearance level, or on a more complex condition that consists of multiple filters.
You use fine-grained controls to specify who can access particular rows within a table or particular members within a cube dimension. These controls often subset data by a user characteristic such as employee ID or organizational unit. For example, a table that contains patient medical information might be protected by row-level permissions that enable each doctor to see only those rows that contain data about that doctor's patients.
Unlike other access controls, fine-grained controls are based on filters and rely on target data that is modeled to work with those filters. When fine-grained controls are used, there are three possible authorization decision outcomes for a user request to view data:
Grant
The requesting user can access all data.
Deny
The requesting user can't access any data.
Conditional Grant
The requesting user can access only the data that meets specified filtering conditions.

What Implementations are Available?

Each of the following components offers an implementation of fine-grained controls:
Information Maps (BI Row-Level Permissions)
provide filtering for SAS data sets and third-party relational data accessed through an information map. You define and assign the filters in SAS Information Map Studio or with the INFOMAPS procedure.
This feature is practical for use with large, dimensionally modeled data marts. BI row-level permissions do not require a specific data model. BI row-level permissions can limit access to data within fact tables without incurring the performance cost of directly filtering those tables. This is accomplished by ensuring that access to a fact table is always subject to an inner join with a filtered dimension (the filtering criteria is usually some type of identity information). This feature enables you to define granular access to third-party data without requiring you to maintain individual user accounts within those database systems.
CAUTION:
Not all SAS clients require that users go through information maps in order to access data. Comprehensive security that incorporates BI row-level permissions requires a specialized configuration that is supported only by SAS Web Report Studio.
SAS OLAP Server
provides filtering for SAS OLAP data using MDX expressions. You define and assign the filters in SAS Management Console, SAS OLAP Cube Studio, or SAS Data Integration Studio. See SAS OLAP Server: User's Guide.
SAS Scalable Performance Data Server
enables you to define database views that filter rows based on the user ID of the connecting client. This functionality is provided by the @SPDSUSR system variable. The metadata-based identity-driven properties are not available in this implementation. See the SAS Scalable Performance Data Server: Administrator’s Guide.
The following table compares the implementations:
Comparison of Fine-Grained Control Implementations
Implementation
Secure
Graphical Filter Creation
Authorization UI
Metadata-Aware
Identity-Driven
OLAP member-level
check
check
check
check
check
SPD Server row-level
check
check
BI row-level
caution icon
check
check
check
check

About Identity-Driven Properties

Overview of Identity-Driven Properties

It is often necessary to make per-person access distinctions for the rows in a table or the members in a dimension. You can make a separate filter for each user (such as where name="joe"). However, if you have more than a few users, this approach quickly becomes cumbersome. The more efficient alternative is to create a dynamic filter (such as where name="&name;") that can discover and insert the correct, user-specific value into the WHERE expression each time access is requested.
To create a dynamic filter, use an identity-driven property as the value against which values in the target data are compared. This list explains how the substitution works:
  1. Each identity-driven property corresponds to a characteristic (such as name, user ID, or external identity).
  2. Each user's values for these characteristics (such as joe, WinXP\joe, or 607189) are stored in the metadata.
  3. The identity-driven property is aware of the user ID with which a client authenticated and can locate information that is stored in the metadata for that user ID.
  4. Each time it receives a request, the identity-driven property substitutes a user-specific value into the filter expression.
Note: This discussion is not applicable to the SPD Server, which has its own implementation of identity-based filtering.
These are the most useful identity-driven properties:
SAS.Userid
returns an authenticated user ID, normalized to the uppercase format USERID or USERID@DOMAIN.
SAS.ExternalIdentity
returns a site-specific value (for example, employee ID). This property is often useful because its values are likely to match user information in your data. An identity can have more than one external identity value. However, only the first value is returned. Unlike the values for other identity-driven properties, values for this property are not always populated in the metadata. See External Identities.
SAS.IdentityGroups
returns a list of the groups and roles that this identity belongs to (directly, indirectly, or implicitly). The list contains the group and role names, as displayed in the Name field on the General tab for each group or role.
SAS.PersonName
returns a user name, as displayed in the Name field in the user's general properties.
These identity-driven properties are also supported:
SAS.IdentityGroupName
returns a group name, as displayed in the Name field in the group's general properties. If a user logs on with an ID that is stored in a login on a group definition, then the name of the group that owns that login is returned. If a user logs on with a user ID that is not stored in the metadata, then the PUBLIC group is returned.
This property is useful only in the unusual circumstance where a user logs on with the user ID that is defined for a group login. In almost all cases, a user logs on with a user ID that is defined for an individual user definition. Not all applications allow a group to log on. This property is not supported if client-side pooling is used.
SAS.IdentityName
returns a user name or group name, as displayed in the Name field in the general properties for the user or group. This property is a generalization of SAS.PersonName and SAS.IdentityGroupName.
Note: In certain circumstances, a connecting identity might not have a value for the identity-driven property that you are using. This can happen with the ExternalIdentity property (sometimes), the IdentityGroupName property (almost always), or the PersonName property (rarely). When a connecting user doesn't have a value for the property that a query uses, an empty string is returned or the query fails.

Examples of Identity-Driven Properties

For example, to enable each user to see only his or her own salary information, you could give the PUBLIC group a filter that is based on the SAS.PersonName property. At run time, the SAS.PersonName value that is associated with the connected user ID is substituted into the filter. In this way, the query is modified as appropriate for each requesting client.
This table contains examples of filters that are based on identity properties, showing representations of both the generic form and how each filter would be modified when executed by a user named Harry Highpoint. Harry is a member of the ETL and Executives groups. The example assumes that the customer has an employee information table named EmpInfo which includes Name, Category, WinID, Department, and EmpID columns.
Examples of Filters That Use Identity-Driven Properties
As Defined (Generic Form)
As Executed (Resolved Form)
Where EmpInfo.WinID=&SAS.Userid;
Where EmpInfo.WinID="HIGH@WIN"
Where EmpInfo.EmpID=&SAS.ExternalIdentity;
Where EmpInfo.EmpID="123–456–789"
Where EmpInfo.Department IN &SAS.IdentityGroups;
Where EmpInfo.Department IN ('ETL','Executives','PUBLIC','SASUSERS')
Where EmpInfo.Name=&SAS.IdentityName;
Where EmpInfo.Name="Harry Highpoint"
Where EmpInfo.Name=&SAS.PersonName;
Where EmpInfo.Name="Harry Highpoint"
Where EmpInfo.Category=&SAS.IdentityGroupName;
Where EmpInfo.Category=' '1
1Because the user does not log on with a user ID that is stored as part of a group definition, the user has no value for this property. This either returns an empty string (in BI row-level permissions) or causes the query to fail (in other implementations).

Batch Reporting Considerations

When you use fine-grained controls, it is essential to understand that only dynamically generated reports display data based on the access that is defined for the requesting user. Static reports display data based on the access that is defined for the user ID that was used to generate the report. For example:
  • Manually refreshed reports contain cached data (which can be updated by a user action in the report viewer).
  • Pre-generated reports reflect the access of the user ID that was used to generate the report. Identity-specific access distinctions are preserved for pre-generated reports only if you define a separate report job for each user ID.

Permission Precedence Considerations

Note: This discussion applies to only OLAP member-level permissions and authorization-based prefilters. It is not applicable to the SPD Server or to general prefilters in information maps.
Fine-grained controls are assigned to users or groups in the authorization properties of the target dimension or information map. These filters are available only to constrain an explicit grant of the Read permission. These filters are incorporated into the access control evaluation process as permission conditions.
A permission condition is applied only if it is on the setting that is closest to the requesting user. Other conditions that are relevant because of further-removed group memberships don't provide additional, cumulative access. If there is an identity precedence tie between multiple groups at the highest level of identity precedence, those tied conditions are combined in a Boolean OR expression. If the identity precedence tie includes an unconditional grant, access is not limited by any conditions. The following table provides examples:
Precedence for Permission Conditions
Principle
Scenario
Outcome and Explanation
If there are multiple permission conditions that apply to a user because of the user's group memberships, then the highest precedence identity controls the outcome.
A filter on InformationMapA limits Read permission for GroupA.
Another filter on InformationMapA limits Read permission for the SASUSERS group.
The user is a member of both GroupA and SASUSERS.
The user can see only the rows that GroupA is permitted to see. GroupA has higher identity precedence than SASUSERS, so the filters that are assigned to GroupA define the user's access.
If there are multiple permission conditions at the highest level of identity precedence, then any data that is allowed by any of the tied conditions is returned.
A filter on DimensionA limits Read permission for GroupA.
Another filter on DimensionA limits Read permission for GroupB.
The user is a first level member of both GroupA and GroupB.
The user can see any member that is permitted for either GroupA or GroupB.
The following example describes the impact of identity precedence when a manager uses an information map that includes both of the following filters for a SALARY table:
  • A permission condition that is assigned to the SASUSERS group gives each user access to his or her own salary information.
  • A permission condition that is assigned to a Managers group enables each manager to see the salaries of the employees that he or she manages.
When the manager accesses the SALARY table, the filter that is assigned to the Managers group is applied and the filter that is assigned to SASUSERS is ignored. This is because the manager's direct membership in the Managers group has higher identity precedence than the manager's implicit membership in the SASUSERS group. To avoid a situation in which managers can see their employees' salaries but each manager can't see his or her own salary, you can use either of these approaches:
  • Assign the filters to two groups that have the same identity precedence. For example, if you assign the first filter to a general purpose user-defined group (rather than to SASUSERS), and you make each manager a direct member of that group, then managers will have an identity precedence tie between that group and the Managers group. This situation causes the two filters to be combined for members of the Managers group, enabling those users to see any row that is permitted by either filter.
  • Define the Managers filter in a way that encompasses all of the rows that the managers should be able to see. In other words, combine (OR together) the SASUSERS filter and the Managers filter.