Data Access Policy Examples
This page illustrates data access policies and the composability of permissions, row- and column-level policies.
Setup for examples⚓︎
For all of the examples in this page
- project
newscontains tablesrequestsandanother - table
news.requestsholds exactly 1000 rows of fabricated CDN request-style data for different sections of a media site - table
news.anotherholds no rows and exists only to demonstrate permissions and scoping interactions when composing data access policies - table
hydro.logsis a system table mentioned to demonstrate scope applicability. See Hydrologs - role
emptyexists, has no permissions, row, or column policies - roles and policies are combined to illustrate access controls on table
news.requests
Each example describes a scenario involving one or more roles and different combinations of row and column policies.
A fabricated simple table called news.requests holding CDN-like rows for a media site serves as example data.
| Column | Type | Description |
|---|---|---|
section |
string |
A media section, like Business, Lifestyle, Culture, Sports |
client_ip |
ip |
The requester's IPv4 or IPv6 address; perhaps anonymized or truncated |
cciso |
string |
An ISO-3166-2 country code |
response_code |
uint8 |
The logged numeric HTTP status code |
response_bytes |
uint32 |
Number of bytes in the HTTP response payload sent to the client |
Minimal demonstration data and a transform are available.
Summary of example roles⚓︎
Hypothetical data access roles include
- Media specialists who have access to the Sports section, or all client traffic in France but can't see the client IP
- Network operations personnel who are permitted to see the client IP addresses but can't see the media sections.
- Business analysts who can see everything in the table. Here the role is defined separately to demonstrate role composition interactions.
Click on the role link to jump to a section demonstrating the access control.
| Role | Scope | Permissions | Row Filter | Blocked Columns | Notes |
|---|---|---|---|---|---|
nr_sports_sp |
news.requests |
select_sql |
section = 'Sports' |
client_ip |
only Sports; client_ip inaccessible |
nr_fr_sp |
news.requests |
select_sql |
cciso = 'FR' |
client_ip |
only FR; client_ip inaccessible |
nr_netops_sp |
news.requests |
select_sql |
None | section |
all rows; section inaccessible |
nr_analyst_sp |
news.requests |
select_sql |
True |
None | all rows, columns; row filter |
nr_read |
news.requests |
select_sql |
None | None | all rows, columns; table scope |
nr_sports |
None | None | section = 'Sports' |
client_ip |
only Sports; client_ip allowed, see warning |
read_only |
Global | select_sql, etc. |
None | None | all rows, columns; global preset |
empty |
n/a | None | None | None | no access |
Always define scoped permissions in roles with column policies
If the select_sql permission is not present on the same role as a column policy, the column policy doesn't apply. See explanation of example role nr_sports.
Single role examples⚓︎
Default-deny⚓︎
Without explicit permissions, an account has no access and can't see anything.
| Description | |
|---|---|
| Account roles | empty |
| Permissions | None |
| Column policies | None |
| Row policies | None |
Unfettered global access⚓︎
With the global preset read_only role, an account has permissions to read all tables, including news.requests.
| Description | |
|---|---|
| Account roles | read_only |
| Permissions | Global preset permissions: select_sql, show_columns_sql, etc. |
| Column policies | None |
| Row policies | None |
The broad scope of the read_only role grants access to other tables.
Unfettered table scope⚓︎
With table-scoped select_sql permissions, an account can see the whole table, but no other tables.
| Description | |
|---|---|
| Account roles | nr_read |
| Permissions | table-scoped select_sql |
| Column policies | None |
| Row policies | None |
Sports only, empty permissions⚓︎
Without any scoped permissions, an account has no access.
| Description | |
|---|---|
| Account roles | nr_sports |
| Permissions | None |
| Column policies | One: blocked = client_ip |
| Row policies | One: section = 'Sports' |
Sports only, scoped permissions⚓︎
With table-scoped permissions and corresponding row and column policies, an account has tightly controlled access. This is an example of strict composition strategy. Other tables aren't accessible.
| Description | |
|---|---|
| Account roles | nr_sports_sp |
| Permissions | table-scoped select_sql |
| Column policies | One: blocked = client_ip |
| Row policies | One: section = 'Sports' |
France only, scoped permissions⚓︎
This is another example of limiting access to a subset of rows in the news.requests table and forbidding accessibility of the sensitive client_ip column. Other tables are also inaccessible to account with solely this role. This is an example of strict composition strategy.
| Description | |
|---|---|
| Account roles | nr_fr_sp |
| Permissions | table-scoped select_sql |
| Column policies | One: blocked = client_ip |
| Row policies | One: cciso = 'FR' |
Network operations⚓︎
Network personnel require the client_ip for troubleshooting. The column policy blocking the section column illustrated here is arbitrary but becomes relevant when combined with other column policies as shown in Row filters and two column policies.
Accounts with solely this role aren't permitted to see the section column.
| Description | |
|---|---|
| Account roles | nr_netops_sp |
| Permissions | table-scoped select_sql |
| Column policies | One: blocked = section |
| Row policies | None |
Analyst⚓︎
An analyst should be able to see the whole table. The row filter is unnecessary in this single-role example. It becomes relevant when combined with other row policies as shown in Row filters and an empty column policy.
| Description | |
|---|---|
| Account roles | nr_analyst_sp |
| Permissions | table-scoped select_sql |
| Column policies | None |
| Row policies | One: True |
Role combination examples⚓︎
Click on the role combination link to jump to a section demonstrating the access control.
| Combination | COUNT() | Blocked columns | hydro.logs? |
Notes |
|---|---|---|---|---|
nr_sports, read_only |
252 | None | readable | only Sports |
nr_sports_sp, read_only |
252 | client_ip |
readable | only Sports |
nr_sports_sp, nr_fr_sp |
439 | client_ip |
inaccessible | only Sports or client in FR |
nr_fr_sp, nr_netops_sp |
439 | None | inaccessible | only Sports or client in FR |
nr_sports_sp, nr_analyst_sp |
1000 | client_ip |
inaccessible | all rows |
Read-only and unscoped role⚓︎
In this example, the broadly scoped read_only global preset combines with a row filter in nr_sports.
The column client_ip is allowed because role nr_sports lacks any permissions scope. To forbid access to client_ip see the Read-only and scoped role example. See also combining column policies.
| Role | Role | |
|---|---|---|
| Account roles | nr_sports |
read_only |
| Permissions | None | select_sql, etc. |
| Column policies | One: blocked = client_ip |
None |
| Row policies | One: section = 'Sports' |
None |
Effective access, after combination
| Description | |
|---|---|
| Permissions | broadly scoped select_sql, etc. |
| Blocked columns | None |
| Combined row filter | (section = 'Sports') |
The broader scope of the read_only role grants access to other tables.
Read-only and scoped role⚓︎
In this example, the broadly scoped read_only global preset combines with a row filter in nr_sports_sp. Column client_ip is blocked.
| Role | Role | |
|---|---|---|
| Account roles | nr_sports_sp |
read_only |
| Permissions | table-scoped select_sql |
select_sql, etc. |
| Column policies | One: blocked = client_ip |
None |
| Row policies | One: section = 'Sports' |
None |
Effective access, after combination
| Description | |
|---|---|
| Permissions | broadly scoped select_sql, etc. |
| Blocked columns | client_ip |
| Combined row filter | (section = 'Sports') |
The broader scope of the read_only role grants access to other tables.
Different row filters, same column policy⚓︎
Several prior examples compose with the broadly-scoped read_only role. This example uses table-scoped permissions in each role employing the strict composition strategy.
The intermediate row filters in the two roles are joined with an SQL OR to form the final filter expression. The client_ip column isn't allowed since both roles block it.
| Role | Role | |
|---|---|---|
| Account roles | nr_sports_sp |
nr_fr_sp |
| Permissions | table-scoped select_sql |
table-scoped select_sql |
| Column policies | One: blocked = client_ip |
One: blocked = client_ip |
| Row policies | One: section = 'Sports' |
One: cciso = 'FR' |
Effective access, after combination
| Description | |
|---|---|
| Permissions | table scoped select_sql |
| Blocked columns | client_ip |
| Combined row filter | (section = 'Sports') OR (cciso = 'FR') |
The strict scope of permisions prohibits access to other tables.
Two column policies and one row filter⚓︎
In this example, two column policies block different columns. The intersection of blocked columns is the empty set, so all columns in the table are allowed.
The final filter expression is tighter than nr_netops_sp itself because there is no row policy defined. For policy construction, compare this example with the nr_analyst_sp role as shown in Row filters and an empty column policy.
| Role | Role | |
|---|---|---|
| Account roles | nr_netops_sp |
nr_fr_sp |
| Permissions | table-scoped select_sql |
table-scoped select_sql |
| Column policies | One: blocked = section |
One: blocked = client_ip |
| Row policies | None | One: cciso = 'FR' |
Effective access, after combination
| Description | |
|---|---|
| Permissions | table scoped select_sql |
| Blocked columns | None |
| Combined row filter | (cciso = 'FR') |
Row filters and an empty column policy⚓︎
This example demonstrates a permissive final row filter expression and a column policy blocking a sensitive column, client_ip.
- The absence of a column policy on
nr_analyst_spmeans that the column policy fromnr_sports_spapplies. See combining column policies. - The row filter
Truein thenr_analyst_spgrants access to all rows, regardless of other row policies. See combining row policies.
| Role | Role | |
|---|---|---|
| Account roles | nr_sports_sp |
nr_analyst_sp |
| Permissions | table-scoped select_sql |
table-scoped select_sql |
| Column policies | One: blocked = client_ip |
None |
| Row policies | One: section = 'Sports' |
One: True |
Effective access, after combination
| Description | |
|---|---|
| Permissions | broadly scoped select_sql, etc. |
| Blocked columns | client_ip |
| Combined row filter | (section = 'Sports') or (True) |
Policy data⚓︎
API response fragments⚓︎
Column policies for news.requests⚓︎
Column policies for news.requests
Row policies for news.requests⚓︎
Row policies for news.requests
Role nr_sports⚓︎
Role nr_sports
Observe the absence of any permissions at all in the policies attribute of this role. This role is empty.
Role nr_sports_sp⚓︎
Role nr_sports_sp
This role includes table-scoped permissions allowing select_sql for table news.requests.
Role nr_fr_sp⚓︎
Role nr_fr_sp
This role includes table-scoped permissions allowing select_sql for table news.requests.
Role nr_netops_sp⚓︎
Role nr_netops_sp
This role includes table-scoped permissions allowing select_sql for table news.requests.
Role nr_analyst_sp⚓︎
Role nr_analyst_sp
This role includes table-scoped permissions allowing select_sql for table news.requests.
Sample table data⚓︎
Example COUNT() queries for complete access to news.requests
The counts in the queries below match examples of policy combinations illustrated elsewhere in this document.