Dashboard Access Policies
Rill supports granular access policies for dashboards. They allow the dashboard developer to configure dashboard-level, row-level and column-level restrictions based on user attributes such as email address and domain. Our goal with access to policies is to avoid dashboard sprawl by creating a single configuration of the dashboard that can then be sliced or restricted into multiple views via different policies. Using those access controls, a single dashboard can now serve dozens of teams and use cases to ensure consistent metric definitions and better dashboard findability.
Some of the typical use cases include:
- Restricting access to certain dashboards to admin users
- Limiting dashboards to relevent fields or metrics by team for ease of use (creating a lookup and filter by role)
- Limiting access to sensitive dimensions or measures to users from a specific department
- Partner-filtered dashboards where external users can only see the subset of data that relates to them
Access policies only apply to users who have been invited to access the project. They provide granular access control for your data, but are not the first layer of security for your project.
Configuration
You define access policies for dashboards under the security
key in a dashboard's YAML file. The key properties are:
- Dashboard-level access:
access
– a boolean expression that determines if a user can or can't access the dashboard - Row-level access:
row_filter
– a SQL expression that will be injected into theWHERE
clause of all dashboard queries to restrict access to a subset of rows - Column-level access:
include
orexclude
– lists of boolean expressions that determine which dimension and measure names will be available to the user
See the Dashboard YAML reference docs for all the available fields.
See the Examples below for how to set up each type of configuration.
User attributes
When developing access policies, you can leverage a fixed set of user attributes to resolve access at runtime. The attributes are:
.user.email
– the current user's email address, for examplejohn.doe@example.com
(string).user.domain
– the domain of the current user's email address, for exampleexample.com
(string).user.name
- the current user's name, for exampleJohn Doe
(string).user.admin
– a boolean value indicating whether the current user is an org or project admin, for exampletrue
(bool).user.groups
- a list of user groups the user belongs to in the project's org (list of strings), e.g.["marketing","sales","finance"]
Note: Rill requires users to confirm their email address before letting them interact with the platform so a user cannot fake an email address or email domain.
If you require additional user attributes to enforce access policies, see the example for custom attributes below for more details.
Templating and expression evaluation
When a user loads a dashboard, the policies are resolved in two phases:
- The templating engine first replaces expressions like
{{ .user.domain }}
with actual values (Templating reference) - The resulting expression is then evaluated contextually:
- The
access
andif
values are evaluated as SQL expressions and resolved to atrue
orfalse
value - The
row_filter
value is injected into theWHERE
clause of the SQL queries used to render the dashboard
Testing your policies
In Rill Developer
In development (on localhost
), you can test your policies by adding "mock users" to your project and viewing the dashboard as one of them.
In your project's rill.yaml
file, add a mock_users
section. Each mock user must have an email
attribute, and can optionally have name
and admin
attributes. For example:
# rill.yaml
mock_users:
- email: john@yourcompany.com
name: John Doe
admin: true
- email: jane@partnercompany.com
groups:
- partners
- email: anon@unknown.com
On the dashboard page (provided you've added a policy) you'll see a "View as" button in the top right corner. Click this button and select one of your mock users. You'll see the dashboard as that user would see it.
In Rill Cloud (Admin only)
In case you want to test what your users are seeing in Rill Cloud after deploying, you can find this in the dropdown of your account. You will see the actual users in the dropdown of this list, not the mock users defined in the rill.yaml file.
Examples
Restrict dashboard access to users matching specific criteria
Let's say you want to restrict dashboard access to admin users or users whose email domain is example.com
. Add the following clause to your dashboard's YAML:
security:
access: "{{ .user.admin }} OR '{{ .user.domain }}' == 'example.com'"
If the security
section is defined and access
is not, then access
will default to false
, meaning that it won't be accessible to anyone and users will need to invited individually.
Restrict dashboard access to specific user groups
Group membership can be utilized to specify which users have access to a specific dashboard (using the templating function has
). For example:
security:
access: '{{ has "partners" .user.groups }}'
Show only data from the user's own domain
You can limit the data available to the dashboard by applying a filter on the underlying data. Assuming the dashboard's underlying model has a domain
column, adding the following clause to the dashboard's YAML will only show dimension and measure values for the current user's email domain:
security:
access: true
row_filter: "domain = '{{ .user.domain }}'"
The filter
value needs to be valid SQL syntax for a WHERE
clause. It will be injected into every SQL query used to render the dashboard.
Conditionally hide a dashboard dimension or measure
You can include or exclude dimensions and measures based on a boolean expression. For example, to exclude a dimension named ssn
and id
for users whose email domain is not example.com
:
security:
access: true
exclude:
- if: "'{{ .user.domain }}' != 'example.com'"
names:
- ssn
- id
Alternatively, you can explicitly define the dimensions and measures to include using the include
key. It uses the same syntax as exclude
and automatically excludes all names not explicitly defined in the list. See the Dashboard YAML reference for details.
Use wildcards to select all dimensions and measures
When defining inclusion policies, you can easily and automatically select all columns by using names: '*'
as a wildcard. For example:
security:
access: true
include:
- if: true
names:
- ssn
- id
- if: "{{ .user.admin }}"
names: '*'
Note that the '*'
must be quoted (using single or double quotes), and must be provided as a scalar value, not as an entry in a list.
Filter queries based on the user's groups
You can directly inject the groups that a user belongs to into the row filter itself, such as:
security:
access: true
row_filter: "groups IN ('{{ .user.groups | join \"', '\" }}')"
Hide dimensions or measures for members of a certain group
You can check group membership using the templating function has
. For example:
security:
access: true
exclude:
- if: '{{ has "partners" .user.groups }}'
names:
- cost
- profit
Advanced Example: Custom attributes
For some use cases, the built-in user attributes do not provide sufficient context to correctly restrict access. For example, a dashboard for a multi-tenant SaaS application might have a tenant_id
column and external users should only be able to see data for the tenant they belong to.
To support this, we can ingest a separate data source containing mappings of user email addresses to tenant IDs and reference it in the row-level filter.
For example, if we have a mappings.csv
file in the data
directory of our Rill project with the following contents:
email,tenant_id
john.doe@example.com,1
jane.doe@example.com,2
we can ingest it as a regular data source in Rill:
# sources/mappings.yaml
type: local_file
path: data/mappings.csv
(In practice, you would probably ingest the data from a regularly updated export in S3.)
We can now refer to the mappings data using a SQL sub-query as follows:
security:
access: true
row_filter: "tenant_id IN (SELECT tenant_id FROM mappings WHERE email = '{{ .user.email }}')"