Skip to main content
Policy Cover
Datazone’s policy system provides flexible, fine-grained access control through role-based permissions. Policies define what actions users can perform on resources, supporting both flat and hierarchical resource patterns with explicit allow/deny rules.

Key Features

  • Role-based: Policies are bound to roles, not individual users
  • Hierarchical: Support for project-scoped resources (e.g., project:<id>:dataset:*)
  • Explicit deny: Deny statements override allow statements
  • Extra constraints: Resource-specific restrictions (row-level security, column filtering, path prefixes)
  • Wildcard support: Use * for flexible matching across resources and actions
  • Filtered lists: Lists only return the entities you can read (<resource>:read), so a role or scoped API key without pipeline:read sees no pipelines
  • Branch-aware: Optional branch specification for version control
Policy Diagram

Policy Structure

A policy is a list of statements that define access rules:

Fields

Resource Patterns

Resources follow a hierarchical pattern that supports various levels of specificity:

Flat Resources

Hierarchical Resources

Hierarchical patterns enable project-scoped permissions:

Supported Resource Types

  • dataset - Data tables in the lakehouse
  • project - Project containers
  • view - Virtual views over datasets
  • schedule - Automated execution schedules
  • extract - Data ingestion jobs
  • compute - Compute resources
  • api_key - API authentication keys
  • user - User accounts
  • role - User roles
  • notebook - Interactive analysis notebooks
  • pipeline - Data transformation pipelines
  • endpoint - REST API endpoints
  • intelligent_app - Dashboard applications
  • variable - Environment variables
  • agent - AI agents
  • action - Executable actions
  • organisation - Organisation-level administration
  • orion - Orion logs
  • console - The developer console (console:read shows it)
  • source - Data source connections
  • notification - Notification channels and settings
  • tag - Resource tags
  • ruleset - Data Quality rulesets
  • rule_template - Data Quality Rule Library templates

Actions

Actions follow the <resource>:<action> format and define what operations can be performed:

Action Patterns

  • dataset:read - Read access to datasets
  • dataset:write - Modify datasets
  • dataset:delete - Delete datasets
  • dataset:execute - Execute operations on datasets
  • dataset:manage - Full management access
  • dataset:create - Create new datasets
  • dataset:* - All dataset actions
  • *:read - Read access to all resources
  • *:* - All actions on all resources

Common Actions

Exceptional Actions

Some resources support custom actions beyond the standard CRUD operations:
  • project:read_repository - Read access to project code repository
  • project:write_repository - Write access to project code repository (push commits, merge pull requests)
  • project:pr_create - Permission to open a pull request targeting a branch
  • project:deploy - Permission to deploy a project
  • endpoint:invoke - Permission to call an API endpoint
  • agent:ask - Permission to ask (query) an AI agent

Developer Console

The developer console is shown only to users with console:read. Every built-in role has it. To hide the console, use a role whose policies do not grant console:read, or deny it:
This only hides the console. The queries and requests made from it are still checked against your other permissions.

Manage Permissions and Settings Access

Some parts of the application — mainly the Settings area — are gated by the manage action rather than by read. A user who holds <resource>:manage sees that resource’s menu in Settings and can view its entries. manage grants visibility only. It does not imply creating, editing, or deleting — grant <resource>:create, <resource>:write, or <resource>:delete alongside it for those operations. Previously these areas were visible only to users with organisation:manage. Now each resource can be delegated independently, so you can grant access to a single Settings menu without handing over organisation-wide administration.

Resources that support manage

Example: access to API keys and sources

This policy reveals the API Keys and Source menus in Settings without granting any other organisation administration:
The user can open both menus and see their contents. All other Settings menus stay hidden. Because API keys belong to the user who owns them, api_key:manage is enough to create and revoke their own keys. Sources are shared organisation resources, so this policy does not let them create or delete a source.

Example: adding source create permission

To let the same role also create sources, add source:create on the resource type:
Deleting or editing existing sources requires source:delete and source:write on the instances (for example source:*).
organisation:manage still implies access to every Settings menu. Use the per-resource manage actions when you want to delegate one area only.

Row-Level and Column-Level Security

Datazone supports fine-grained data access control through row-level and column-level restrictions using the extra_constraints field. This enables you to restrict what data users can see within a dataset or view, beyond just granting or denying access to the entire resource. Restrictions are enforced by ClickHouse: Datazone turns them into ClickHouse row policies and column grants for each role, so they apply to every query a user runs, whether from the SQL explorer, the API or anywhere else that queries data as that user. They are synced in the background and take effect within about a minute of saving the policy.

Extra Constraints Structure

For datasets and views, you can specify columnar constraints:

Fields

What the restrictions do depends on the statement’s effect:
A deny statement with restrictions only takes away part of the data. The dataset or view itself stays accessible: it is still listed and can still be queried. A deny without restrictions removes access to the whole resource, as usual.

Row-Level Restrictions

Row-level restrictions apply SQL conditions to filter which rows a user can access:
The user only sees rows where country = 'USA' AND department = 'Sales', as if every query on this dataset carried that filter. To hide some rows and keep the rest, use deny. Combined with a broad allow, this gives access to everything except the matching rows:
How row restrictions combine:
  • Several allow statements on the same dataset: a row is visible if it matches any of them.
  • deny statements always apply on top: a row matching a deny is hidden even if an allow matches it.
  • NULL values: a deny only hides rows where the condition is true. Rows where it evaluates to NULL (for example city is NULL) stay visible.

Column-Level Restrictions

With allow, only the listed columns are readable:
With deny, the listed columns are hidden and everything else stays readable. For example, read access to all datasets except one sensitive column:
How column restrictions combine:
  • An allow listing columns limits the dataset to those columns, even if the same role also has broader access to it (for example through dataset:*).
  • When both an allow and a deny list columns of the same dataset, the readable columns are the allowed ones minus the denied ones.
  • Columns added to the dataset later are hidden under an allow list and visible under a deny list. Prefer an allow list for sensitive data.

Querying a dataset with hidden columns

Hidden columns are not silently dropped from results. ClickHouse rejects any query that reads a hidden column, including SELECT * and filters such as WHERE password = ...:

Combined Restrictions

You can use both row and column restrictions together:

Users with Several Roles

Row and column restrictions are combined differently when a user has more than one role:
  • Column restrictions are applied per role, and roles add up: if any of the user’s roles can read a column, the user can read it. A column hidden in one role is still readable if another role grants the whole dataset.
  • Row restrictions apply to the user directly, whichever role they come from: a row restriction in one role narrows the rows the user sees even if another role grants the whole dataset.
Important Restrictions for Row/Column-Level Security:When using extra_constraints with row_level_restrictions or column_level_restrictions:
  1. Must target a specific resource: Use dataset:<object_id> or view:<object_id>. Wildcards like dataset:* and project-scoped patterns like project:<id>:dataset:* or project:<id>:view:<id> are rejected
  2. Read-only actions: Only dataset:read or view:read actions are allowed
  3. Single action: Statement must contain exactly one action
  4. Existing columns: Every column in column_level_restrictions must exist in the dataset or view. A misspelled name is rejected when the policy is saved (checked once the dataset or view has a schema)
Invalid examples:
  • ❌ "resource": "dataset:*" (wildcard not allowed)
  • ❌ "resource": "project:507f1f77bcf86cd799439011:dataset:*" (project-scoped pattern not allowed)
  • ❌ "actions": ["dataset:read", "dataset:write"] (multiple actions)
  • ❌ "actions": ["dataset:*"] (wildcard action not allowed)
  • ❌ "actions": ["dataset:write"] (write action not allowed)
  • ❌ "column_level_restrictions": ["pasword"] (no such column)
Valid example:
  • ✅ "resource": "dataset:507f1f77bcf86cd799439011" with "actions": ["dataset:read"]
Empty constraints ({}, or both lists empty) restrict nothing and are ignored, so they are accepted on any resource.

Limitations

  • Restrictions follow column names, not columns. If a column is renamed (for example password to pwd), a restriction on the old name no longer applies to it. Review the policies of a dataset after renaming its columns.
  • Row conditions are checked by ClickHouse at query time. A condition that refers to a column the dataset does not have makes every query on that dataset fail for the affected users, until the condition is fixed.
  • Views are restricted separately. A view reads its source with its own permissions, so restrictions on a dataset do not carry over to views built on it. Add the same restrictions to the view.
  • Only queries through ClickHouse are covered. Restrictions are enforced by the database, not by the files underneath it.

Policy Examples

Read-Only Access

Grant read access to all resources:

Dataset Admin

Full control over all datasets:

Project Admin

Full control over a specific project and all its resources:
This allows the user to:
  • Manage the project itself (project:*)
  • Create and manage all child resources (datasets, notebooks, pipelines, etc.)

Restricted Access with Deny

Allow read access to all datasets except one specific dataset:
Deny statements always override allow statements, regardless of order.

Project-Scoped Dataset Access

Grant access to datasets within a specific project only:

Branch Protection

Repository permissions can be scoped to a branch with the branch field. Combined with the separation between project:write_repository (pushing commits and merging pull requests) and project:pr_create (opening a pull request), this lets you protect a branch such as main while keeping the rest of the project fully editable.
How this evaluates: The result is a familiar protected-branch workflow: contributors work on feature branches and open pull requests into main, but nobody with this policy can push or merge into main directly. Grant merge rights to a separate reviewer role that is not denied project:write_repository on main.
project:pr_create is checked against the base branch of the pull request — the branch being merged into. To block pull requests into main entirely, add project:pr_create to the deny statement’s actions.

Data Analyst Role

Typical permissions for a data analyst:

Built-in Policies

Datazone provides several built-in policies for common use cases:

Admin Policy

Full access to all resources:

Access Map

The Access Map shows who can do what as a graph: users on the left, the roles they hold in the middle, and the policies those roles grant on the right. Open it from Settings → Users → Map, or click Open in access map on any user, role or policy page.
Access map with users, roles and policies
  • Add to map: search users, roles or policies in the side panel, then click one or drag it onto the canvas.
  • Include connections: when on, adding a user also adds their roles and the policies those roles grant; adding a role adds its policies; adding a policy adds the roles that use it.
  • Inspect: click a node to see its connections, effective policies, and each statement’s resources, actions, row filters and restricted columns.
  • Add several users side by side to compare their access, and use Full screen or Clear map from the toolbar.

Best Practices

Policy Design

  1. Start restrictive: Begin with minimal permissions and add as needed
  2. Use hierarchical patterns: Organize permissions by project for better management
  3. Leverage deny sparingly: Use deny for exceptions to broad allow rules
  4. Document policies: Add clear descriptions to explain policy intent

Role Assignment

  1. Bind to roles only: Policies are assigned to roles, not individual users
  2. Create role hierarchies: Use multiple roles for different permission levels (Viewer, Editor, Admin)
  3. Audit regularly: Review policy assignments periodically

Performance

  1. Cache aware: Policies are cached; changes may take a few seconds to propagate
  2. Granular resources: Use specific resource IDs when possible to reduce evaluation complexity
  3. Minimize deny statements: They require checking all policies

Security

  1. Principle of least privilege: Grant only necessary permissions
  2. Explicit denies: Use deny statements to override broad allows for sensitive resources
  3. Extra constraints: Apply row-level and column-level security for sensitive data
  4. Path restrictions: Use path_prefix constraints to sandbox project access

Validation Rules

Policies are validated automatically to ensure correctness:

Action Format

  • Must follow <resource>:<action> pattern
  • Both parts must be lowercase with underscores
  • Wildcards allowed: *:*, dataset:*, *:read
Valid:
  • dataset:read
  • project:*
  • *:*
Invalid:
  • dataset (missing action)
  • Dataset:Read (uppercase)
  • read (missing resource)

Resource Pattern

  • Must be valid resource type or wildcard
  • ObjectIds must be valid MongoDB ObjectIds
  • Hierarchical patterns must follow parent:<id>:child format
Valid:
  • dataset:*
  • project:507f1f77bcf86cd799439011
  • project:507f1f77bcf86cd799439011:dataset:*
Invalid:
  • dataset:invalid-id
  • project::dataset:*

Action-Resource Matching

Actions must match the resource type they’re applied to:
Exception: Wildcard actions (*:*) can be used on any resource.

Troubleshooting

Permission Denied Errors

If you encounter permission denied errors:
  1. Check user roles: Verify the user has the appropriate role assigned
  2. Review policy statements: Ensure the policy includes the required action and resource
  3. Look for deny statements: Check if an explicit deny is overriding an allow
  4. Verify resource IDs: Ensure you’re using the correct resource identifier
  5. Check cache: Wait a few seconds for policy changes to propagate

”Not enough privileges” on a Dataset You Can Read

If a query fails with Not enough privileges on a dataset the user can otherwise read, a column restriction hides one of the columns the query uses:
  1. Avoid SELECT *: List the columns explicitly, or exclude the hidden ones with SELECT * EXCEPT (column)
  2. Check filters and joins: Using a hidden column in WHERE, JOIN or GROUP BY also needs access to it
  3. Review the policy: Look for column_level_restrictions on the dataset in the user’s roles
If rows are missing rather than a query failing, a row restriction is filtering them. Restriction changes take about a minute to apply.

Hierarchical Permissions Not Working

If project-scoped permissions aren’t working:
  1. Verify pattern format: Use project:<id>:* not project:*:<id>
  2. Check parent context: Ensure the resource creation includes project reference
  3. Review cache: Hierarchical relationships are cached; wait 5 minutes or invalidate cache
  4. Validate ObjectIds: All IDs must be valid MongoDB ObjectIds

Performance Issues

If policy evaluation is slow:
  1. Reduce policy complexity: Simplify nested hierarchies
  2. Use specific resources: Prefer dataset:<id> over broad wildcards when possible
  3. Monitor cache health: Ensure Redis is functioning properly
  4. Check database queries: Hierarchical policies should use cache, not database

Roles

Learn about role management and user assignment

Authentication

Understand authentication and token management

API Keys

Generate and manage API keys for programmatic access

Projects

Organize resources within projects