Skip to content

Commit 3338d66

Browse files
danyi1212zeevmoneyCopilot
authored
Enhance Trino integration docs (#608)
Co-authored-by: Zeev Manilovich <zeevmoney@users.noreply.github.com> Co-authored-by: Zeev Manilovich <zeevmanilovich@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent f1700d1 commit 3338d66

File tree

1 file changed

+101
-3
lines changed

1 file changed

+101
-3
lines changed

docs/integrations/database-access-control/trino-integration.mdx

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ For more information, see the [Trino documentation](https://trino.io/docs/curren
134134

135135
### Row-level Filtering
136136

137-
Row filters let you attach SQL predicates that Trino appends as `WHERE` clauses based on a users permissions:
137+
Row filters let you attach SQL predicates that Trino appends as `WHERE` clauses based on a user's permissions:
138138

139139
```4:16:trino-authz-example/trino-authz.yaml
140140
rowFilters:
@@ -157,6 +157,48 @@ You can review the [Audit Logs](https://app.permit.io/audit-log) to see the Perm
157157

158158
For more information, see the [Trino documentation](https://trino.io/docs/current/security/opa-access-control.html#row-filtering).
159159

160+
#### User-Specific Filtering with `current_user`
161+
162+
Filter expressions can reference Trino's [`current_user`](https://trino.io/docs/current/functions/session.html) function, enabling user-specific data access. The key pattern:
163+
164+
- **Permit** determines **which filter** applies (based on the user's role/permissions).
165+
- **The SQL expression** determines **which rows** using `current_user`.
166+
167+
```yaml
168+
rowFilters:
169+
# Ensure users have only ONE of `view_all` or `view_own`, not both.
170+
# If a user has both actions, Trino combines them with AND, resulting in `1=1 AND
171+
# owner_id = current_user` - which only returns owned records, not all records.
172+
trino_table_postgresql_public_orders:
173+
- action: view_all
174+
expression: "1=1" # Admins see everything
175+
- action: view_own
176+
expression: "owner_id = current_user" # Users see only their records
177+
```
178+
179+
Assign `view_all` to admin roles and `view_own` to regular users in Permit. When a user queries the table, the appropriate filter is applied based on their permissions.
180+
181+
:::tip
182+
For `current_user` to return the correct identity, configure [Trino authentication](#trino-authentication) (e.g., JWT) to pass the user identifier.
183+
:::
184+
185+
#### Subqueries in Filter Expressions
186+
187+
Filters can include subqueries for more complex scoping:
188+
189+
```yaml
190+
rowFilters:
191+
trino_table_postgresql_public_documents:
192+
- action: view_team_data
193+
expression: "team_id IN (SELECT team_id FROM team_members WHERE user_id = current_user)"
194+
```
195+
196+
This resolves team membership at query time, allowing users to see data for all teams they belong to.
197+
198+
:::warning
199+
When a user has multiple filter actions, Trino chains them with `AND` (intersection). Design role assignments so users typically have one filter action per table.
200+
:::
201+
160202
## Reference
161203

162204
### Architecture
@@ -339,9 +381,38 @@ Using that, you can combine Permit authorization for application users, and Trin
339381
340382
### Trino authentication
341383
342-
You can use Trino's several Authentication mechanisms to identify the user, like [JWT](https://trino.io/docs/current/security/jwt.html) or [OAuth2](https://trino.io/docs/current/security/oauth2.html).
384+
You can use Trino's authentication mechanisms to identify the user, like [JWT](https://trino.io/docs/current/security/jwt.html) or [OAuth2](https://trino.io/docs/current/security/oauth2.html).
385+
386+
Using it, you can pass-through the user's identity to Trino, so the PDP can check against the application user's identity and permissions. This is essential for row filters that use `current_user`.
387+
388+
#### JWT Authentication Setup
389+
390+
JWT authentication allows your application to pass user identity to Trino via tokens. The user identifier extracted from the JWT becomes the value of `current_user` in Trino queries.
343391
344-
Using it, you can pass-through the user's identity to Trino, so the PDP can check against the application user's identity and permissions.
392+
1. Configure Trino's JWT authentication in `/etc/trino/config.properties`:
393+
394+
```properties
395+
http-server.authentication.type=JWT
396+
http-server.authentication.jwt.key-file=https://cluster.example.net/.well-known/jwks.json
397+
http-server.authentication.jwt.principal-field=sub
398+
```
399+
400+
The `principal-field` setting determines which JWT claim becomes `current_user`. Common options:
401+
- `sub` (subject) - standard JWT claim for user identity
402+
- `user_id` - if your tokens use a custom claim
403+
- `email` - if using email as the user identifier
404+
405+
2. When your application queries Trino, include the JWT in the Authorization header:
406+
407+
```http
408+
Authorization: Bearer <jwt-token>
409+
```
410+
411+
3. The user identifier from the JWT is then available as `current_user` in row filter expressions.
412+
413+
:::tip
414+
Make sure the user identifier in your JWT matches the format used in your row filter expressions. For example, if your `employee_id` column contains UUIDs, configure `principal-field` to extract the UUID claim from your JWT.
415+
:::
345416

346417
For more information, see the [Trino authentication documentation](https://trino.io/docs/current/security/authentication-types.html).
347418

@@ -365,3 +436,30 @@ We recommend the following performance optimizations:
365436
- Scale the PDP cluster horizontally to handle the load.
366437

367438
For more information, see the [Permit PDP Deployment Models](/concepts/pdp/overview#production-deployment-models) documentation.
439+
440+
## FAQ
441+
442+
### Can I combine RBAC/ABAC with row-level filtering?
443+
444+
Yes. Permit's policy model (RBAC/ABAC) determines **which filter action** a user has.
445+
The row filter SQL expression determines **which rows** they see.
446+
For example, a "manager" role derived via RBAC could grant a `view_team_data` action that applies a team-scoped filter.
447+
448+
### Are row filters dynamic?
449+
450+
Filter expressions are static SQL defined in YAML, but they can use Trino's `current_user` function which resolves dynamically at query time. This allows `owner_id = current_user` to return different rows for different users.
451+
452+
### How does `current_user` get populated?
453+
454+
From Trino's authentication. With JWT, configure `http-server.authentication.jwt.principal-field` to specify which claim becomes `current_user`. See [JWT Authentication Setup](#jwt-authentication-setup).
455+
456+
### Can filters access user attributes from Permit?
457+
458+
Not directly. Store user-to-group mappings in a database table and use subqueries:
459+
460+
```yaml
461+
rowFilters:
462+
your_table_resource:
463+
- action: your_action
464+
expression: "team_id IN (SELECT team_id FROM team_members WHERE user_id = current_user)"
465+
```

0 commit comments

Comments
 (0)