Data access policies
Data access policies provide a holistic mechanism to manage member-level and row-level security for different data access roles. You can define access control rules in data model files, allowing for an organized and maintainable approach to security.
Data access roles
Each request to Cube includes a security context, which can contain
information about the user. You can use the context_to_roles configuration
option to derive the user's roles from the security context:
A user can have more than one role.
Policies
You can define policies that target specific roles and contain member-level and (or) row-level security rules:
cubes:
- name: orders
# ...
access_policy:
# For the `manager` role,
# allow access to all members
# but filter rows by the user's country
- role: manager
conditions:
- if: "{ securityContext.is_EMEA_based }"
member_level:
includes: "*"
row_level:
filters:
- member: country
operator: equals
values: [ "{ securityContext.country }" ]You can define data access policies both in cubes and views. If you use views, it is recommended to keep all your cubes private and define access policies in views only. It will make your security rules easier to maintain and reason about, especially when it comes to member-level access.
For more details on available parameters, check out the data access policies reference.
Policy evaluation
When processing a request, Cube will evaluate the data access policies and combine them
with relevant custom security rules, e.g., public parameters for member-level security
and query_rewrite filters for row-level security.
If multiple access policies apply to a request, they are combined together using the OR semantics. For example, if a user has two roles with different policies, the user will get the union of the permissions in these policies.
Member-level access
Member-level security rules in data access policies are combined together
with public parameters of cube and view members using the AND semantics.
Both will apply to the request.
When querying a view, member-level security rules defined in the view are not combined together with member-level security rules defined in relevant cubes. Only the ones from the view will apply to the request.
This is consistent with how column-level security works in SQL databases. If you have a view that exposes a subset of columns from a table, it doesnt matter if the columns in the table are public or not, the view will expose them anyway.
Row-level access
Row-level filters in data access policies are combined together with filters defined
using the query_rewrite configuration option.
Both will apply to the request.
When querying a view, row-level filters defined in the view are combined together with row-level filters defined in relevant cubes. Both will apply to the request.
This is consistent with how row-level security works in SQL databases. If you have a view that exposes a subset of rows from another view, the result set will be filtered by the row-level security rules of both views.
Troubleshooting
Common pitfalls
Be careful with the any role shorthand (role: "*") in data access
policies that don't restrict access on member and row level. Given that policies for
multiple roles are combined together using the OR semantics,
a policy that allows access for any role without restrictions on a certain level will
effectively grant unrestricted access on that level to all users:
cubes:
- name: orders
# ...
access_policy:
# No access on member level, __full access__ on row level for any role
- role: "*"
member_level:
includes: []
# Some restrictions on row level for the `restricted` role
- role: restricted
row_level:
filters:
- member: country
operator: equals
values: [ "USA" ]In the example above, all users will have full access to all members and all rows of the
orders cube, regardless of their roles, because of the first policy applies to any
role and is combined with the second one using the OR semantics.