KaelioDocs

Table Access Rules

Control which database tables users can query by allowing or blocking access with patterns and conditions.

Table access rules determine which tables users can query on a data source. You define rules using exact table names or glob patterns, and optionally restrict them to users who match specific conditions.

Rules are evaluated in the table_rules list within your policy YAML. When no rule matches a table, the default_allow_tables setting decides whether access is granted or denied.

Basic Usage

Each rule specifies a table_name and whether access is allowed:

policy.yaml
version: "1.0"
default_allow_tables: true

table_rules:
  - table_name: audit_logs
    allowed: false
  - table_name: public_stats
    allowed: true

With this policy, queries against audit_logs are blocked while public_stats is explicitly allowed. All other tables fall through to default_allow_tables: true, so they remain accessible.

Before and After

Given the policy above, here is how a query is affected:

User writes
SELECT * FROM orders JOIN audit_logs ON orders.id = audit_logs.order_id
Result
-- Query blocked: access to table "audit_logs" is denied

Because audit_logs is blocked, the entire query fails -- Kaelio does not silently remove the blocked table and return partial results.

When a query references a blocked table, the entire query is rejected. This applies even if the blocked table is only used in a JOIN, subquery, or CTE. Kaelio never returns partial results from queries that touch restricted tables.

Glob Patterns

Use glob patterns to match multiple tables with a single rule. This is useful when your database follows a naming convention.

policy.yaml
version: "1.0"
default_allow_tables: true

table_rules:
  - table_name: internal_*
    allowed: false
  - table_name: "*_pii"
    allowed: false
  - table_name: tmp_*
    allowed: false

This blocks all tables starting with internal_, ending with _pii, or starting with tmp_.

PatternMatchesDoes Not Match
*All tables--
analytics_*analytics_events, analytics_sessionsraw_analytics
*_logsaudit_logs, access_logslogs_archive
internal_*internal_users, internal_configusers_internal

Rules are evaluated in order: exact names match first, then more specific glob patterns, then the * wildcard. See the Policy YAML Reference for full details on matching precedence.

Conditional Access

Add a condition to a rule so it only applies when the user's security properties match. This lets you grant different access levels based on department, role, or any other user attribute.

policy.yaml
version: "1.0"
default_allow_tables: false

table_rules:
  - table_name: compensation
    allowed: true
    condition:
      department: "hr"
  - table_name: compensation
    allowed: true
    condition:
      department: "finance"
  - table_name: sales_pipeline
    allowed: true
    condition:
      department: ["sales", "marketing"]

In this example:

  • The compensation table is only accessible to users whose department property is hr or finance
  • The sales_pipeline table is accessible to users in sales or marketing
  • All other tables are blocked because default_allow_tables is false

When a condition has multiple keys, all keys must match (AND logic). If a user does not have a required property set, the condition fails and the rule is skipped.

Multi-key condition
table_rules:
  - table_name: payroll
    allowed: true
    condition:
      department: "hr"
      role: "manager"

This rule only applies to users who have department set to hr and role set to manager.

If a conditional rule does not match and no other rule covers the table, default_allow_tables determines access. Set user security properties in each user's profile under the Security tab.

Common Patterns

Block Sensitive Tables

Keep the default open and block specific tables that contain sensitive data:

policy.yaml
version: "1.0"
default_allow_tables: true

table_rules:
  - table_name: audit_logs
    allowed: false
  - table_name: "*_pii"
    allowed: false
  - table_name: internal_*
    allowed: false

Allowlist Mode

Block everything by default and explicitly allow only the tables users need:

policy.yaml
version: "1.0"
default_allow_tables: false

table_rules:
  - table_name: products
    allowed: true
  - table_name: orders
    allowed: true
  - table_name: customers
    allowed: true

Department-Based Access

Combine conditions with a default-deny policy to scope access per team:

policy.yaml
version: "1.0"
default_allow_tables: false

table_rules:
  - table_name: revenue_*
    allowed: true
    condition:
      department: "finance"
  - table_name: campaign_*
    allowed: true
    condition:
      department: "marketing"
  - table_name: company_directory
    allowed: true

Finance users can query any table starting with revenue_, marketing users can query tables starting with campaign_, and company_directory is available to everyone.

On this page